Транслятор Zend Framework 3 из БД

Я недавно начал работать с ZF3 и работаю над интернационализацией проекта.

Мне удалось заставить его работать, но я хотел бы, чтобы переводчик получал переводы из базы данных, а не читал их из файлов .mo. Таким образом, пользователь сможет редактировать их в административной части приложения.

Я установил модуль Zend\Mvc\I18n, зарегистрировал его как view_helper

// module's module.config.php:    
'view_helpers' => [
    'invokables' => [
        'translate' => \Zend\I18n\View\Helper\Translate::class
    ]
]

и вместо

// module's module.config.php:
'translator' => [
    'locale' => 'en_US',
    'translation_file_patterns' => [
        [
            'type'     => 'gettext',
            'base_dir' => __DIR__ . '/../language',
            'pattern'  => '%s.mo',
        ],
    ],
]

у меня есть

// module's module.config.php:
'translator' => [
    'locale' => 'en_US',
    'remote_translation' => [
        [
            'type' => Service\Database::class
        ]
    ]
]

и служба базы данных реализует RemoteLoaderInterface, как требуется в документации, прямо сейчас он имеет жестко запрограммированный массив, но позже будет заменен фактическим запросом.

//Database.php
namespace Core\Service;

use Zend\I18n\Translator\Loader\RemoteLoaderInterface;

class Database implements RemoteLoaderInterface {

    private $entityManager;

    public function __construct($entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function load($locale, $textDomain)
    {
        $array = [];
        $array['and'] = 'i';
        return $array;
    }
}

В моей макетной печати

// layout.phtml
$this->translate("and") // prints "i"

приводит к «i», чего я и хотел.

Теперь моя проблема заключается в том, как передать диспетчер сущностей доктрины службе базы данных? Я знаю, что в таких ситуациях мне нужно использовать фабрику, и у меня есть готовая

//DatabaseFactory.php
namespace Core\Service\Factory;

use Core\Service\Database;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;

class DatabaseFactory implements FactoryInterface 
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $entityManager = $container->get('doctrine.entitymanager.orm_default');

        // Instantiate the service and inject dependencies
        return new Database($entityManager);
    }

}

но я просто не могу передать его в конфигурации модуля, потому что он требует, чтобы класс реализовал RemoteLoaderInterface.

// module's module.config.php:   
'remote_translation' => [
    [
        'type' => Service\Factory\DatabaseFactory::class // does not work
    ]
]

Есть ли обходной путь или что-то, что мне не хватает? Любая помощь будет оценена по достоинству. Спасибо за совет!


person Dragan    schedule 07.06.2017    source источник


Ответы (2)


Это немного сложно. Вы должны настроить фабрику загрузчиков переводов до того, как произойдет рендеринг.

module\Application\src\Module.php:

public function init (ModuleManager $manager)
{
    $eventManager = $manager->getEventManager();
    $sharedEventManager = $eventManager->getSharedManager();

    $sharedEventManager->attach(__NAMESPACE__, 'dispatch',
        [$this, 'onDispatch'], 100);
}

public function onDispatch (MvcEvent $event)
{
    $translator = $event->getApplication ()->getServiceManager ()->get (\Zend\I18n\Translator\TranslatorInterface::class);
    $translator->getPluginManager()->setFactory(\Application\Translator\Database::class, \Application\Translator\DatabaseFactory::class);

Я не знаю другого способа настроить локатор сервисов для переводчика.

person akond    schedule 07.06.2017

Похоже, вы забыли зарегистрировать класс и его фабрику в сервис-менеджере:

// module's module.config.php
'translator' => [
    'loaderpluginmanager' => [
        'factories' => [
            Core\Service\Database::class => Service\Factory\DatabaseFactory::class,
        ],
    ],
    'locale' => 'en_US',
    'remote_translation' => [
        [
            'type' => Core\Service\Database::class
        ]
    ]
]
person xtreamwayz    schedule 07.06.2017
comment
Не имеет никакого значения :( Переводчик по-прежнему напрямую обращается к классу базы данных, а не к DatabaseFactory. - person Dragan; 07.06.2017
comment
@Dragan Я обновил свой ответ, чтобы он использовал менеджер плагинов. Если это не сработает, то я не знаю. - person xtreamwayz; 07.06.2017