I'm trying to pass translation strings as key-value pairs through a Twig template without having to assign them again one by one.
I have my translations in a file translations/messages.fr.yaml
. Example:
entity:
foo: some translation
bar: another translation
third:
title: one more
Currently I pass translations through the Twig template in a JS code block, using the 'trans' filter:
const translations = {
foo: "{{'entity.foo'|trans}}",
bar: "{{'entity.bar'|trans}}",
third: {
title: "{{'entity.third.title'|trans}}"
}
}
Is there a way how to pass all properties of 'entity' directly? Could I access the translations as an object and pass it into the variable via JSON (as a Twig variable or, if necessary, echoing something with <?php ... ?>
)?
I'm aware that I could use AJAX but I am trying to pass the data in the template.
I solved it with a function getTranslations
that retrieves the catalogue and merges it with the fallback catalogue. Then it calls the recursive function addToArray
to create a multi-dimensional array from the dot-separated key segments:
function addToArray(array $keySegments, array|string $translations, string $translation) : array|string
{
if (count($keySegments) === 0) {
return $translation;
}
if (!is_array($translations)) {
// syntax error in yaml file - a dot inside a key name
return $translations;
}
$keySegment = array_shift($keySegments);
if (!isset($translations[$keySegment])) {
$translations[$keySegment] = [];
}
$translations[$keySegment] = addToArray($keySegments, $translations[$keySegment], $translation);
return $translations;
}
function getTranslations(Symfony\Contracts\Translation\TranslatorInterface $translator) : array
{
// replace 'messages' with the required domain
$catalogue = array_merge(
$translator->getCatalogue()->getFallbackCatalogue()->all('messages'),
$translator->getCatalogue()->all('messages')
);
$translations = [];
foreach ($catalogue as $key => $translation) {
$keySegments = explode('.', $key);
$translations = array_merge($translations, addToArray($keySegments, $translations, $translation));
}
return $translations;
}
In the twig template I use the output in a script block:
const translations = JSON.parse(`{{translations|json_encode|raw}}`);