我想要做的是,根据用户浏览器发送的Accept-Language
,翻译代码内字符串(__('translatable string')
)和我配置的字段具有TranslateBehavior
。
已添加
DispatcherFactory::add('LocaleSelector', ['locales' => ['en_US', 'el_GR']]);
<{1>}中的,以便使用用户浏览器发送的bootstrap.php
自动设置区域设置。这很好用,并将语言环境设置为Accept-Language
或en_US
。
我也设置了i18n(跟http://book.cakephp.org/3.0/en/orm/behaviors/translate.html之后),因为我希望我的桌子的某些字段可以翻译。
当然,我的代码中有一些字符串,它们不是来自数据库而需要翻译。我使用el_GR
函数。
让用户通过__()
请求希腊语(Accept-Language
),然后将语言环境设置为el_GR
。函数el_GR
将开箱即用,因为它正是它所需要的。
但是,__()
无效,因为它需要TranslateBehavior
,而不是gre
。
如何让这两个人同时工作,而他们期望同一语言的语言环境价值不同?
答案 0 :(得分:1)
翻译行为不会对区域设置标识符格式施加任何限制。可能的值仅受数据库列类型/长度的限制。
因此,只需使用en_US
和el_GR
作为翻译表记录,您就应该做得很好。
答案 1 :(得分:1)
经过@ndm的长时间讨论和帮助,我采取了以下措施使其发挥作用:
执行适当的更改后,请完全清除tmp
目录并更新编写器。这解决了LocaleSelector
的问题,在设置适当的语言环境时,我的数据库没有被翻译。
问题是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);
}
}
在bootstrap.php
:
DispatcherFactory::add('LocaleSelector', ['locales' => ['el_GR' => ['el', 'el_GR', 'el-GR'], 'en_US']]);
在上面的示例中,el
的所有值el_GR
,el-GR
和Accept-Language
都将导致设置的区域设置el_GR
。此外,如果Accept-Language
具有en_US
值,则会设置该值。因此,它支持将许多不同的值设置为一个特定的语言环境,并且还支持默认的LocaleSelector
行为。
i18n
表的区域设置列必须设置为'el_GR'(在此示例中)。这是必要的,因为它是代码内可翻译字符串所期望的(使用__()
函数的字符串)。因此,通过设置'el_GR'(而不是文档中提到的'gre'),您将使代码内可翻译字符串和数据库可翻译字段开箱即用。就是这样!