数据库翻译Zend Framework 2

时间:2014-04-04 10:47:30

标签: php zend-framework zend-framework2 translation

我在ZF2中从数据库创建自定义转换器时遇到问题。我有一个这样的数据库enter image description here

和文件:

1)应用程序/ module.config.php

'service_manager' => array(
    'abstract_factories' => array(),
    'factories' => array(
        'translator' => function  (\Zend\ServiceManager\ServiceManager $serviceManager)
            {
                $pluginManager = new \Zend\I18n\Translator\LoaderPluginManager();
                $pluginManager->setServiceLocator($serviceManager);
                $pluginManager->setFactory('DatabaseTranslationLoaderFactory', function($serviceManager)
                {
                    $translator = new \Zend\I18n\Translator\DatabaseTranslationLoaderFactory();
                    return $translator->createService($serviceManager);
                });
                $translator = new \Zend\I18n\Translator\Translator(array());
                $translator->setFallbackLocale('en_US');
                $translator->setPluginManager($pluginManager);
                $translator->addRemoteTranslations('DatabaseTranslationLoaderFactory');
                return $translator;
            },
    ),
),

'translator' => array(
    'locale' => 'en_US',
    'translation_file_patterns' => array(
        array(
            'type'     => 'Zend\I18n\Translator\Loader\Database',
            'base_dir' => __DIR__ . '/../language',
            'pattern'  => '%s.mo',
        ),
    ),
),

2)Zend / I18n / Translator / Loader / Database.php

<?php

namespace Zend\I18n\Translator\Loader;

use Zend\Db\Adapter\Adapter;
use Zend\Db\Sql\Sql;
use Zend\I18n\Translator\Plural\Rule as PluralRule;
use Zend\I18n\Translator\TextDomain;


class Database implements RemoteLoaderInterface {

protected $dbAdapter;


public $dbAdapter;


public function __construct(Adapter $dbAdapter = null)
{
    if ($dbAdapter === null)
    {
        $configArray = array('driver' => 'Pdo_Mysql',
            'database' => 'dbname',
            'username' => 'username',
            'password' => 'pswd',
            'hostname' => 'localhost',
            'charset' => 'utf-8',
        );
        $dbAdapter = new Adapter($configArray);
    }
    $this->dbAdapter = $dbAdapter;
}


public function load($locale, $textDomain)
{
    $sql = new Sql($this->dbAdapter);
    $select = $sql->select('ic_var')->columns(array('value'))
                  ->where(array('language' => $locale, 'name' => $textDomain));

    $messages = $this->dbAdapter->query(
        $sql->getSqlStringForSqlObject($select),
        Adapter::QUERY_MODE_EXECUTE
    );

    $textDomain = new TextDomain();

    foreach ($messages as $message) {
        if (isset($textDomain[$message['name']])) {
            if (!is_array($textDomain[$message['name']])) {
                $textDomain[$message['name']] = array(
                    $message['plural_index'] => $textDomain[$message['name']]
                );
            }
            $textDomain[$message['name']][$message['plural_index']] = $message['value'];
        } else {
            $textDomain[$message['name']] = $message['value'];
        }
    }
    return $textDomain;
}
}

3)Zend / I18n / Translator / DatabaseTranslationLoaderFactory.php

<?php

namespace Zend\I18n\Translator;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\I18n\Translator\Loader\Database;

class DatabaseTranslationLoaderFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        return new Database($serviceLocator->get('Zend\Db\Adapter\Adapter'));
    }
}

4)Application / Module.php

public function onBootstrap(MvcEvent $e)
{
    $translator = $e->getApplication()->getServiceManager()->get('translator');
    $translator->addTranslationFile(
        'DatabaseTranslationLoader',
        'text-domain',
        'text-domain'
    );
}

但是翻译不起作用,因为db adapter在loader中找不到:

  

致命错误:未捕获的异常'Zend \ I18n \ Exception \ RuntimeException',消息'指定的加载程序不是文件加载器'

感谢您的回答!

2 个答案:

答案 0 :(得分:2)

首先,您不应在Zend命名空间中定义自定义类,因为这是为ZF2库保留的命名空间,您不希望在供应商目录中触摸(或添加)文件。 只需将自定义类放在供应商文件夹之外的您自己的命名空间中。即MyI18n

您可以在module.config.php中将自定义远程加载程序注册到pluginManager。

return array(
    'translator' => array(
        'loaderpluginmanager' => array(
            'factories' => array(
                'database' => 'MyI18n\Translator\DatabaseTranslationLoaderFactory',
            )
        ),
        'remote_translation' => array(
            array(
                'type' => 'database' //This sets the database loader for the default textDomain
            ),
        ),
    )
);

如果要添加自定义加载程序,则不必覆盖转换程序工厂,因此只需删除Module.php中的代码即可。 Als删除translation_file_patterns下的配置,因为这只是文件加载器所必需的。

修改

要使上述工作正常,您需要覆盖TranslatorServiceFactory,因为ZF不支持在插件管理器上注册自定义加载器。

namespace MyNamespace\Translator;

use Zend\Mvc\Service\TranslatorServiceFactory as BaseTranslatorFactory;

class TranslatorServiceFactory extends BaseTranslatorFactory
{
    /**
     * @param ServiceLocatorInterface $serviceLocator
     * @return MvcTranslator
     */
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $translator = parent::createService($serviceLocator);

        $config = $serviceLocator->get('Config');
        $pluginManagerConfig = isset($config['translator']['loaderpluginmanager']) ? $config['translator']['loaderpluginmanager'] : array();
        $pluginManager = new LoaderPluginManager(new Config($pluginManagerConfig));
        $pluginManager->setServiceLocator($serviceLocator);
        $translator->setPluginManager($pluginManager);

        return $translator;
    }
}

现在在服务配置中注册您的自定义工厂:

class Module
{
    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'MvcTranslator' => 'MyNamespace\Translator\TranslatorServiceFactory',
            )
        )
    }
}

答案 1 :(得分:0)

我将自定义远程加载程序注册到module.config.php中的pluginManager,如下所示

'translator' => [
    'loaderpluginmanager' => [
        'factories' => [
            'database' => function($lpm){
                $sm = $lpm->getServiceLocator();
                $loader = new Zf2Translation\Loader\DatabaseTranslationLoader($sm);
                return $loader;
            },
        ],
    ],
    'remote_translation' => [
        [
            'type' => 'database', 
        ],
    ],
]

Next在Database Loader类

use Zend\I18n\Translator\Loader\RemoteLoaderInterface;
class DatabaseTranslationLoader implements RemoteLoaderInterface
{
    protected $dbAdapter;
    protected $sm;

    public function __construct(ServiceManager $sm)
    {
        $this->sm = $sm;
        $this->dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
    }
}

我希望它有所帮助。