如何加载两个mo文件进行gettext本地化

时间:2014-01-24 13:22:41

标签: php mysql gettext

我正在尝试解决此问题以加载两个mo文件。 我有两个mo文件都有不同的msgid和msgstr。

我的文件夹结构如下。 本地/ EN_US / LC_MESSAGES / lang.mo 本地/ EN_US / LC_MESSAGES / brand.mo

以下代码我用来加载mo文件。

define('PROJECT_DIR', realpath('./'));
define('LOCALE_DIR', PROJECT_DIR .'/locale');
define('DEFAULT_LOCALE', 'en_US');
$encoding = 'UTF-8';
$locale = (isset($_SESSION['lang']))? $_SESSION['lang'] : DEFAULT_LOCALE;
// gettext setup
T_setlocale(LC_MESSAGES, $locale);
// Set the text domain as 'messages'
$our_domain = 'lang';
T_bindtextdomain($our_domain, LOCALE_DIR);
T_bind_textdomain_codeset($our_domain, $encoding);
T_textdomain($our_domain);

如何在此添加一个mo文件

2 个答案:

答案 0 :(得分:5)

我们的想法是将您的字符串分类为不同的类别

locale/
    en/                    <-- language
       LC_MESSAGES/        <-- category
           messages.mo     <-- domain
           brands.mo       <-- domain

您将不同的域绑定到区域设置目录,以告诉gettext可以在哪里找到哪个域。然后,选择默认域,在调用_('Foo')时使用该域。然后,您可以使用更专业的功能来切换域或类别:

_('Foo')                                  // LC_MESSAGES/messages.mo
dgettext('brands', 'Foo')                 // LC_MESSAGES/brands.mo
dcgettext('brands', 'Foo', LC_MONETARY)   // LC_MONETARY/brands.mo

我们的想法是在源代码中对字符串进行分类。

答案 1 :(得分:1)

您可以再次使用bindtextdomaintextdomain函数将新的翻译文件设置为默认资源。

简化它的一个好方法是创建实用函数,让我们说selectTrFile($filename),它会使它看起来像这样:

function selectTrFile($trFile) {
    bindtextdomain($trFile, TRANSLATION_BASE_DIR); // The constant being the path of you translations file directory
    textdomain($trFile);
}

// Now set the first file

selectTrFile('default');

// Do your stuff with this translations file

selectTrFile('anotherTranslationsResource');

// Have fun with it

你甚至可以通过将上面的功能包装在另一个自动为你切换的文件中来加快速度。

function _f($msgid, $trFile){ // called _f to make it very short to type
    selectTrFile($trFile); // Switch the translations file
    return _($msgid); // Return the translated string
}

// Then wrap your translations filenames in short variables
$f1 = 'lang';
$f2 = 'brand';

// now you can translate Strings easily from one file or another.
_f("to be translated in file 'lang'", $f1);
_f("to be translated in file 'brand'", $f2);

如果您不知道翻译是哪个文件,则可以使用此功能代替_f($msgid, $trFile);

function _f($msgid){

     selectTrFile('lang'); // or set a variable containing the filename and use it

     $msgstr = _($msgid);

     if($msgstr == $msgid){ // if the Strings are equals it means that there was no match in the first file
         selectTrFile('brand'); // or set a variable containing the second filename and use it
         $msgstr = _$(msgid);
     }

     return $msgstr;
 }

最后一个问题是它可能会减慢很多过程,我不知道在什么时候。您可以通过不每次更改为'lang'来优化它,如果字符串未被翻译或类似的话,查看实际的那个。

修改

我认为您不能同时加载多个翻译资源。这对于msgid的冲突来说太危险了。你最好制作一个更大的.mo文件,而不是加载多个文件。

这就是为什么msgfmt确保在编译时没有冲突的msgids的原因。不要害怕非常大的.po / .mo文件。 Mo是一种编译且速度非常快的格式。

现在可能出现的问题是有一个非常笨拙的.po文件。为避免这种情况,最好的方法是将文件分开。

有两种方法可以通过文件或子喷射来分隔各个部分。如果您计划在多个文件中使用相同的翻译(如果您正确使用包含文件,这种情况很少发生),您可以按主题分开。

通常的方法是按文件分隔并添加字符串来自的注释。

##
# File : /your/php/file.php
##
msgid "first String in file.php"
msgstr "first translation in file.php
.
.
.
##
# File : your/other/file.php
##
msgid "other translation"
msgstr "and then you go on"

因此,如果您正确遵循指南,则永远不需要从单个.php文件访问多个.mo文件。

有关更多信息,请参阅here (The format of PO files)