【问题标题】:CakePHP how to change __() language in the same requestCakePHP 如何在同一个请求中更改 __() 语言
【发布时间】:2015-03-28 13:16:52
【问题描述】:

我正在使用 CakePHP 2.6.x

我的应用已本地化为法语和英语。英语是默认设置。

我的翻译文件目前如下所示:

/app/Locale/eng/LC_MESSAGES/default.po
/app/Locale/fra/LC_MESSAGES/default.po

在我看来,我通常可以像这样显示当前语言的本地化文本:

echo __("Foo");

但是,在某些情况下,我需要覆盖当前语言并返回特定语言的翻译。我的理解是__d() 就是为了这个。但是,以下内容对我不起作用:

echo __d("fra", "Foo");

[更正:__d 不是为了这个。]

这似乎总是返回当前语言的翻译。基本上只是链接__()

经过多次反复试验,我重命名了法语 .PO 文件...

/app/Locale/fra/LC_MESSAGES/fra.po

...然后__d("fra", "Foo"); 确实按预期工作。但随后__() 不再 工作了。更改文件名后,__() 的所有实例都以默认语言返回文本。

我做错了什么?如何让__d()_() 同时工作?或者问同样问题的另一种方式:如何在同一请求中更改 __() 使用的语言?

更新

我的第一直觉是尝试一下 Lars 在下面建议的方法。但由于某种原因,它不起作用。我在电子邮件视图中执行以下操作:

    Configure::write("Config.language", "fra");
    $this->log(Configure::read("Config.language")); //'fra'
    $this->log( __("yes") ); //'yes'

请注意,配置语言设置正确。但是__() 会忽略它,并且无论如何都会呼应当前的语言。 (顺便说一句,我检查过,是/oui 在 PO 文件中)

【问题讨论】:

  • 可能的快速解决方法:在 LC_MESSAGES 目录中创建一个从 default.po 到 fra.po 的符号链接,例如ln -s default.po fra.po.
  • @marian0 嗯。那个黑客可能会奏效,但我怀疑它会在未来给我带来痛苦:-)。我真的需要弄清楚我做错了什么导致 Cake 的 l10n 不能按预期工作。
  • 我认为您尝试做的事情是不可能的。 __d 函数不用于覆盖语言,它用于选择另一个语言文件当前设置的语言中。
  • 不,恐怕不会。您可以在执行__ 之前切换语言,然后再切换回来,我猜。当你选择走这条路时,你想达到什么目标?
  • 如果配置的语言没有被使用,尽管有正确的文件可用,请检查会话中是否设置了语言(CakeSession::read('Config.language')),这是在Configure上使用的,并确保您在更改翻译后已清除缓存 tmp/cache/persistent

标签: php cakephp localization internationalization gettext


【解决方案1】:

最好的办法是在通话之前更改设置的语言,然后再改回来:

$before = Configure::read('Config.language');
Configure::write('Config.language', 'fra');
echo __('Your String');
Configure::write('Config.language', $before);

你甚至可以把它放到一个函数中:

function __lang($string, $language) {
    $before = Configure::read('Config.language');
    Configure::write('Config.language', $language);
    echo __($string);
    Configure::write('Config.language', $before);
}

编辑

正如 mdm 在 cmets 中解释的那样,这基本上就是 I18N::translate 函数的作用。

如果这个(和我的功能)不起作用,我猜你的翻译文件有问题。您是否尝试过在全球范围内切换到目标语言?这会打印正确的字符串吗?

要绕过所有配置和会话值,您可以简单地依赖 I18N::translate 函数:

function __lang($string, $language) {
    echo I18N::translate($string, null, null, I18n::LC_MESSAGES, null, $language);
}

【讨论】:

  • 也许还可以解释I18N::translate() 的直接用法(在这里您可以显式传递一种用于配置的语言)和I18N::insertArgs(),就像_*() 方法在内部做的那样。
  • @ndm 这听起来正是我需要的。没有?
  • @Lars 您的解决方案是我尝试过但无法开始工作的方法。我正在更新我的问题以显示问题...
  • @ndm 我不知道他们存在 ;)
  • 我编辑了我的答案以直接使用 I18N 类,这应该忽略所有当前的语言设置。
【解决方案2】:

按照@ndm 的建议,我编写了一个小实用程序,用于在请求中“切换”语言。

我是这样使用它的:

App::uses('L10nTool', 'Lib');
$L10n = new L10nTool();
$L10n->startToggleLg("fra");
...
//Bonjour, mon ami
...
$L10n->stopToggleLg();//Back to initial language

稍后我可能会添加另一种方法,类似于 Lars 的回答,用于在单个方法中执行一个快速字符串。但是现在我正在用“切换”语言做一些电子邮件逻辑,所以这样做对我来说更容易。

代码如下:

<?php
App::uses('AppHelper', 'View/Helper');
App::uses('CakeSession', 'Model/Datasource');

class L10nTool {

    public $start_lg;
    public $use_session = FALSE;

    public function startToggleLg($lg) {

        if (CakeSession::check("Config.language")) { 
            $this->start_lg = CakeSession::read("Config.language");
            $this->use_session = TRUE;
        } else {
            $this->start_lg = Configure::read("Config.language");
        }

        if ( $this->use_session ) {
            CakeSession::write("Config.language", $lg);
        } else {
            Configure::write("Config.language", $lg);
        }

    }

    public function stopToggleLg($lg = NULL) {

        $lg = ($lg) ? $lg : $this->start_lg;

        if ( $this->use_session ) {
            CakeSession::write("Config.language", $lg);
        } else {
            Configure::write("Config.language", $lg);
        }        

    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-13
    • 1970-01-01
    • 2021-03-05
    • 2015-08-03
    • 1970-01-01
    • 2022-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多