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

Pra*_*n D 4 php mysql gettext

我试图解决这个加载两个mo文件.我有两个mo文件都有不同的msgid和msgstr.

我的文件夹结构如下.local/en_US/LC_MESSAGES/lang.mo local/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);
Run Code Online (Sandbox Code Playgroud)

我怎么能在这里添加一个mo文件

dec*_*eze 5

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

locale/
    en/                    <-- language
       LC_MESSAGES/        <-- category
           messages.mo     <-- domain
           brands.mo       <-- domain
Run Code Online (Sandbox Code Playgroud)

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

_('Foo')                                  // LC_MESSAGES/messages.mo
dgettext('brands', 'Foo')                 // LC_MESSAGES/brands.mo
dcgettext('brands', 'Foo', LC_MONETARY)   // LC_MONETARY/brands.mo
Run Code Online (Sandbox Code Playgroud)

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


Joh*_*ide 2

您只需再次使用bindtextdomain和函数即可将新的翻译文件设置为默认资源。textdomain

简化它的一个好方法是创建实用函数,假设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
Run Code Online (Sandbox Code Playgroud)

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

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);
Run Code Online (Sandbox Code Playgroud)

如果您不知道翻译在哪个文件中,您可以使用此功能来代替_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;
 }
Run Code Online (Sandbox Code Playgroud)

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

编辑

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

这就是 msgfmt 确保编译时不存在冲突的 msgid 的原因。不要害怕非常大的 .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"
Run Code Online (Sandbox Code Playgroud)

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

请参阅此处(PO 文件的格式)了解更多信息。