我知道这是一个老问题,但我觉得答案从头到尾都缺乏更实际的方法。这就是我使用 PHP's gettext library 和 Poedit 在 Debian 服务器上不使用任何其他 PHP 库的情况下所做的翻译工作:
准备步骤 1:在服务器上安装 gettext 和语言环境
我不确定其他操作系统是如何做到这一点的,但对于 Debian,你可以这样做:
sudo apt-get install gettext
sudo dpkg-reconfigure locales
编辑:我认为 Ubuntu 与 Debian 相同,但显然略有不同。有关在 Ubuntu 上安装语言环境的说明,请参阅 this page。
确保选择所有您要使用的语言环境。然后您应该会看到类似的内容:
Generating locales (this might take a while)...
en_US.UTF-8... done
es_MX.UTF-8... done
fr_FR.UTF-8... done
zh_CN.UTF-8... done
Generation complete.
注意:确保为每种语言选择正确的变体和字符编码(最有可能是UTF-8)。如果你安装es_MX.UTF-8 并尝试使用es_ES.UTF-8 或es_MX.ISO-8859-1 将无法正常工作。
准备步骤2:在译者电脑上安装Poedit
Poedit 可从大多数 Linux 操作系统的软件存储库中获得。对于基于 Debian,只需执行:
sudo apt-get install poedit
对于 Windows 和 Mac,请访问:https://poedit.net/download
开始编码:
好的,现在您可以开始编码了。我写了以下gettext() 包装函数来翻译单数和复数:
function __($text, $plural=null, $number=null) {
if (!isset($plural)) {
return _($text);
}
return ngettext($text, $plural, $number);
}
示例用法:
// Singular
echo __('Hello world');
// Plural
$exp = 3;
printf(
__(
'Your account will expire in %d day',
'Your account will expire in %d days',
$exp
),
$exp
);
这适用于所有语言,不仅是复数为 n != 1 的任何语言 - 这包括具有多种复数类型的语言。
您也可以像这样添加翻译注释:
/** NOTE: The name Coconut Hotel is a brand name and shouldn't be
translated.
*/
echo __('Welcome to Coconut Hotel');
您可以将文本从 NOTE 更改为您想要的任何内容,但您必须在下面的 shell 脚本中更改它。 重要提示:译者注释必须是注释的一部分紧接在 __() 函数之前,否则当我们扫描 PHP 文件以查找可翻译的字符串。
// Warning! THIS WILL NOT WORK!
/* NOTE: This translator's note will not be picked up because it is
not immediately preceding the __() function. */
printf(
__(
'Your account will expire in %d day',
'Your account will expire in %d days',
$exp
),
$exp
);
// Warning! THIS WILL NOT WORK!
准备好将字符串发送给翻译人员后,将以下内容保存为应用程序根目录中的 shell 脚本(例如 update.sh):
#!/bin/sh
find . -iname "*.php" | xargs xgettext --add-comments=NOTE --keyword=__:1,2 --keyword=__ --from-code=UTF-8 -o i18n.pot
find . -name '*.po' | xargs -I{} msgmerge -U {} i18n.pot
要执行它,只需:
cd /path/to/script && sh update.sh
这将递归扫描该目录中的所有 PHP 文件并创建一个 .pot 文件(我称之为 i18n.pot,但您可以随意命名)并更新它找到的任何现有 .po 文件新的字符串。
然后,我们需要创建将存储所有语言环境文件的目录,每个语言环境一个。它们的格式必须为./locale/{locale}/LC_MESSAGES。例如:
cd /path/to/your/project
mkdir -p ./locale/en_US.UTF-8/LC_MESSAGES
mkdir -p ./locale/es_MX.UTF-8/LC_MESSAGES
# ...etc.
您需要决定要使用的文本域。这可以是您想要的任何内容,但脚本将在该语言的 LC_MESSAGES 文件夹中查找名为 {yourTextDomain}.mo 的文件。将以下内容放入您的 PHP 脚本中:
define('TEXT_DOMAIN', 'yourdomain');
bindtextdomain(TEXT_DOMAIN, __DIR__.'/locale');
textdomain(TEXT_DOMAIN);
bind_textdomain_codeset(TEXT_DOMAIN, 'UTF-8');
然后要实际切换到另一个语言环境,请执行以下操作:
$lang = 'es_MX.UTF-8'; // Change this to the language you want to use
if (setlocale(LC_ALL, $lang) === false) {
throw new Exception("Server error: The $lang locale is not installed");
}
putenv('LC_ALL='.$lang));
最初,您将上述脚本生成的.pot 文件发送给翻译人员。然后他们打开 Poedit 并点击File > New from POT/PO file。当他们保存它时,他们需要将它保存为{yourTextDomain}.po。 {yourTextDomain} 需要与您在 PHP 脚本中的文本域完全相同。当他们保存它时,它将自动创建.po 文件和.mo 文件。完成翻译后,这两个文件都需要保存在该语言的LC_MESSAGES 目录中。
现在,当您更新 PHP 文件中的字符串时,只需重新执行 shell 脚本并将新更新的 .po 文件发送给翻译人员。然后他们翻译字符串,.po 和 .mo 文件都需要重新上传。
就是这样。设置起来可能有点困难,但是一旦设置并运行起来,就真的很容易了。