I'm working on a Symfony (2.7.4) website where some users have their own language resources for their own locales. For example, a user might have two locales (for example fr
and en
) and another user could also have one or all of these locales.
Each user has the ability to edit its own translations in a third party app, so translations are not shared between users.
I would like to be able to load the appropriate (YML or XLIFF) resources file when accessing a user's page, based on the locale (which is defined in the URL) and the user (could be its ID or anything that identifies it).
For example, when visiting user99.my-domain.ext/fr/
I'd like to add [base_directory]/user99/messages.fr.yml
to the resources loaded by the Translator so it overrides the keys in the base messages.fr.yml
.
I've tried to inject the Translator in my service, but I can only use it for reading translations, not adding any. What would be the best way to do that? Or is doing it in a service is too late? Maybe the Kernel is a better place?
Any help is appreciated!
Note: I'm using the YAML format in my examples, but any of the Symfony-known formats is eligible.
I chose to use a custom Twig filter, so I can decide when I want user specific translations and when I want generic ones.
Here's my extension (my users are in fact Domain
instances):
<?php
// src/AppBundle/Twig/DomainTranslationExtension
namespace AppBundle\Twig;
use AppBundle\Document\Domain;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Translation\Loader\YamlFileLoader;
use Symfony\Component\Translation\Translator;
class DomainTranslationExtension extends \Twig_Extension {
/**
* @var ContainerInterface
*/
protected $container;
/**
* @var Translator
*/
protected $translator;
/**
* @var string
*/
protected $locale;
/**
* @var Domain
*/
protected $domain;
public function setContainer(ContainerInterface $container) {
$this->container = $container;
$this->locale = $this->container->get('request_stack')->getMasterRequest()->getLocale();
$domainService = $this->container->get('app.domain_service');
$this->domain = $domainService->getDomain();
// TODO: File loading error check
$this->translator = new Translator($this->locale);
$this->translator->addLoader('yaml', new YamlFileLoader());
$this->translator->addResource('yaml', 'path/to/domain-translations/' . $this->domain->getSlug() . '/messages.' . $this->locale . '.yml', $this->locale);
}
public function getFilters() {
return array(
new \Twig_SimpleFilter('transDomain', array($this, 'transDomain')),
);
}
public function transDomain($s) {
$trans = $this->translator->trans($s);
// Falling back to default translation if custom isn't available
if ($trans == $s) {
$trans = $this->container->get('translator')->trans($s);
}
return $trans;
}
public function getName() {
return 'app_translation_extension';
}
}
Declared like that in app/config/services.yml
:
app.domain_service:
class: AppBundle\Services\DomainService
arguments: [ @request_stack, @doctrine_mongodb, @translation.loader ]
And used like that in a Twig file:
{{ 'my.translation.key'|transDomain }}
I hope this helps, thanks!
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments