使TranslateBehavior和可翻译字符串同时工作

时间:2015-09-24 09:33:31

标签: cakephp translation locale cakephp-3.0

  • 我想要什么

我想要做的是,根据用户浏览器发送的Accept-Language,翻译代码内字符串(__('translatable string'))和我配置的字段具有TranslateBehavior

的表格
  • 我做了什么

已添加

DispatcherFactory::add('LocaleSelector', ['locales' => ['en_US', 'el_GR']]);
<{1>}中的

,以便使用用户浏览器发送的bootstrap.php自动设置区域设置。这很好用,并将语言环境设置为Accept-Languageen_US

我也设置了i18n(跟http://book.cakephp.org/3.0/en/orm/behaviors/translate.html之后),因为我希望我的桌子的某些字段可以翻译。

当然,我的代码中有一些字符串,它们不是来自数据库而需要翻译。我使用el_GR函数。

  • 问题

让用户通过__()请求希腊语(Accept-Language),然后将语言环境设置为el_GR。函数el_GR将开箱即用,因为它正是它所需要的。

但是,__()无效,因为它需要TranslateBehavior,而不是gre

如何让这两个人同时工作,而他们期望同一语言的语言环境价值不同?

2 个答案:

答案 0 :(得分:1)

翻译行为不会对区域设置标识符格式施加任何限制。可能的值仅受数据库列类型/长度的限制。

因此,只需使用en_USel_GR作为翻译表记录,您就应该做得很好。

答案 1 :(得分:1)

经过@ndm的长时间讨论和帮助,我采取了以下措施使其发挥作用:

  1. 执行适当的更改后,请完全清除tmp目录并更新编写器。这解决了LocaleSelector的问题,在设置适当的语言环境时,我的数据库没有被翻译。

  2. 问题是Accept-Language标头可以包含多个值。您希望其中许多与特定区域设置匹配。这样,您就可以为数据库和可翻译字符串提供相同的区域设置。为了解决这个问题,我制作了自己的LocaleSelectorFilter并将其放在src/Routing/Filter中。它会覆盖默认的LocaleSelectorFilter

    名称空间Cake \ Routing \ Filter;

    使用Cake \ Event \ Event; 使用Cake \ I18n \ I18n; 使用Cake \ Routing \ DispatcherFilter; 使用Locale;

    类LocaleSelectorFilter扩展DispatcherFilter {

    protected $_locales = [];
    
    public function __construct($config = [])
    {
        parent::__construct($config);
        if (!empty($config['locales'])) {
            $this->_locales = $config['locales'];
        }
    }
    
    private function matchLocaleWithConfigValue($localeFromHeader)
    {
        foreach ($this->_locales as $locale => $acceptableValues) {
            // $acceptableValues is either an array or a single string
            if (!$locale) {
                // single string
                if ($localeFromHeader === $acceptableValues) {
                    return $acceptableValues;
                }
            } else {
                // array
                foreach ($acceptableValues as $acceptableValue) {
                    if ($localeFromHeader === $acceptableValue) {
                        return $locale;
                    }
                }
            }
        }
    
        return false;
    }
    
    public function beforeDispatch(Event $event)
    {
        $request = $event->data['request'];
        $locale = Locale::acceptFromHttp($request->header('Accept-Language'));
    
        if (!$locale) {
            // no locale set in the headers
            return;
        }
    
        if (empty($this->_locales)) {
            // any locale value allowed
            I18n::locale($locale);
            return;
        }
    
        // search whether the requested language is in the accepted ones
        $localeConfigMatch = $this->matchLocaleWithConfigValue($locale);
    
        if (!$localeConfigMatch) {
            // no locale matches the header, leave the default one
            return;
        }
    
        // match was found, switch locale
        I18n::locale($localeConfigMatch);
    }
    

    }

  3. bootstrap.php

    中使用它
    DispatcherFactory::add('LocaleSelector', ['locales' => ['el_GR' => ['el', 'el_GR', 'el-GR'], 'en_US']]);
    

    在上面的示例中,el的所有值el_GRel-GRAccept-Language都将导致设置的区域设置el_GR。此外,如果Accept-Language具有en_US值,则会设置该值。因此,它支持将许多不同的值设置为一个特定的语言环境,并且还支持默认的LocaleSelector行为。

    1. 您的i18n表的区域设置列必须设置为'el_GR'(在此示例中)。这是必要的,因为它是代码内可翻译字符串所期望的(使用__()函数的字符串)。因此,通过设置'el_GR'(而不是文档中提到的'gre'),您将使代码内可翻译字符串和数据库可翻译字段开箱即用。
    2. 就是这样!