国际化简单 PHP 网站的最佳方式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6953528/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way to internationalize simple PHP website
提问by Kakawait
I have to develop a pretty simple php website so I don't need framework. But it's must support multi language (EN/FR/CHINESE). I have looked for php built in system and I found two ways :
我必须开发一个非常简单的 php 网站,所以我不需要框架。但它必须支持多语言(EN/FR/CHINESE)。我一直在寻找内置系统的 php,我找到了两种方法:
- intl module from php5.3 (http://php.net/manual/fr/book.intl.php)
- gettext (http://php.net/manual/fr/book.gettext.php)
- 来自 php5.3 的 intl 模块(http://php.net/manual/fr/book.intl.php)
- gettext ( http://php.net/manual/fr/book.gettext.php)
I have no experience in i18n without framework, so any advices about what's the simplest wayto support multi language ?
我没有没有框架的 i18n 经验,所以对支持多语言的最简单方法有什么建议吗?
At end I just need a function that search translation into file (one file by language).
EQ :
trans('hello');
最后,我只需要一个将翻译搜索到文件(按语言一个文件)的功能。情商:
trans('hello');
=> en.yaml (yaml or not, it's an example)
=> en.yaml(yaml 与否,这是一个例子)
hello: "Hello world!"
=> fr.yaml
=> fr.yaml
hello: "Bonjour tout le monde !"
And if possible I prefer Pure PHP implementations
如果可能的话,我更喜欢纯 PHP 实现
回答by Stefan Gehrig
Although ext/gettext
and ext/intl
are both related to i18 (internationalization), gettext
deals with translation while intl
deals with internationalizing things like number and date display, sorting orders and transliteration. So you'd actually need both for a complete i18-solution. Depending on your needs you may come up with an home-brew solution relying on the extensions mentioned above or your use components provided by some framework:
虽然ext/gettext
和ext/intl
都与 i18(国际化)有关,但gettext
处理翻译,同时intl
处理数字和日期显示、排序顺序和音译等国际化问题。因此,对于完整的 i18 解决方案,您实际上需要两者。根据您的需求,您可能会根据上述扩展或某些框架提供的使用组件提出自制解决方案:
- Translation
- Internationalization
- Zend Framework
Zend_Locale
- Zend Framework
- 翻译
- 国际化
- Zend 框架
Zend_Locale
- Zend 框架
If you only need translation and the site is simple enough, perhaps your simple solution (reading a translation configuration file into an PHP array, using a simple function to retrieve a token) might be the easiest.
如果您只需要翻译并且站点足够简单,那么您的简单解决方案(将翻译配置文件读入 PHP 数组,使用简单函数检索令牌)可能是最简单的。
The most simple solution I can think of is:
我能想到的最简单的解决方案是:
$translation = array(
'Hello world!' => array(
'fr' => 'Bonjour tout le monde!',
'de' => 'Hallo Welt!'
)
);
if (!function_exists('gettext')) {
function _($token, $lang = null) {
global $translation;
if ( empty($lang)
|| !array_key_exists($token, $translation)
|| !array_key_exists($lang, $translation[$token])
) {
return $token;
} else {
return $translation[$token][$lang];
}
}
}
echo _('Hello World!');
回答by Mike
I know this is an old question, but I feel that the answers are lacking a more hands-on approach from start to finish. This is what I did to get translation working using PHP's gettext
libraryand Poeditwithout using any additional PHP libraries on a Debian server:
我知道这是一个古老的问题,但我觉得答案从头到尾都缺乏更实际的方法。这就是我使用PHP 的gettext
库和Poedit进行翻译而不在 Debian 服务器上使用任何其他 PHP 库所做的工作:
Preparation step 1: Install gettext
and the locales on the server
准备步骤 1:gettext
在服务器上安装和语言环境
I am not sure how this is done with other operating systems, but for Debian, you do:
我不确定其他操作系统如何做到这一点,但对于 Debian,您可以:
sudo apt-get install gettext
sudo dpkg-reconfigure locales
Edit: I assumed Ubuntu would be the same as Debian, but apparently it's slightly different. See this pagefor instructions for installing locales on Ubuntu.
编辑:我认为 Ubuntu 将与 Debian 相同,但显然它略有不同。有关在 Ubuntu 上安装语言环境的说明,请参阅此页面。
Make sure you select allof the locales that you want to use. You should then see something like:
确保选择了所有要使用的语言环境。然后你应该看到类似的东西:
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.
Note:Make sure you select the right variantsand character encodings(most likely UTF-8) for each language. If you install es_MX.UTF-8
and try to use es_ES.UTF-8
or es_MX.ISO-8859-1
it won't work.
注意:确保为每种语言选择正确的变体和字符编码(最有可能是 UTF-8)。如果您安装es_MX.UTF-8
并尝试使用es_ES.UTF-8
或es_MX.ISO-8859-1
将无法正常工作。
Preparation step 2: Install Poedit on the translators' computers
准备步骤 2:在译员的电脑上安装 Poedit
Poedit is available from the software repository for most Linux operating systems. For Debian-based, just execute:
Poedit 可从大多数 Linux 操作系统的软件存储库中获得。对于基于 Debian 的,只需执行:
sudo apt-get install poedit
For Windows and Mac, go to: https://poedit.net/download
对于 Windows 和 Mac,请访问:https: //poedit.net/download
Start coding:
开始编码:
Ok, now you're ready to get started coding. I wrote the following gettext()
wrapper function to translate both singular and plurals:
好的,现在您已准备好开始编码。我编写了以下gettext()
包装函数来翻译单数和复数:
function __($text, $plural=null, $number=null) {
if (!isset($plural)) {
return _($text);
}
return ngettext($text, $plural, $number);
}
Example usage:
用法示例:
// Singular
echo __('Hello world');
// Plural
$exp = 3;
printf(
__(
'Your account will expire in %d day',
'Your account will expire in %d days',
$exp
),
$exp
);
This will work for all languages, not only languages where plural is anything where n != 1
- this includes languages with multiple plural types.
这适用于所有语言,而不仅仅是复数在任何地方的n != 1
语言 - 这包括具有多种复数类型的语言。
You can also add translator notes like this:
您还可以像这样添加翻译注释:
/** NOTE: The name Coconut Hotel is a brand name and shouldn't be
translated.
*/
echo __('Welcome to Coconut Hotel');
You can change the text from NOTE
to whatever you want, but you will have to alter it in the shell script below. Important: The translators note must be part of a comment on the line immediately precedingthe __()
function or it won't be picked up when we scan the PHP files for translatable strings.
您可以将文本更改为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!
After you are ready to send the strings off to the translators, save the following as a shell script (e.g. update.sh) in your application's root directory:
准备好将字符串发送给翻译器后,将以下内容保存为应用程序根目录中的 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
To execute it, just do:
要执行它,只需执行以下操作:
cd /path/to/script && sh update.sh
This will recursively scan for all PHP files in that directory and create a .pot
file (I called it i18n.pot
, but feel free to name it whatever you like) and update any existing .po
files it finds with the new strings.
这将递归扫描该目录中的所有 PHP 文件并创建一个.pot
文件(我称之为i18n.pot
,但可以随意命名)并.po
使用新字符串更新它找到的任何现有文件。
We then need to create the directories that all the locale files will be stored, one for each locale. They need to be of the format ./locale/{locale}/LC_MESSAGES
. For example:
然后我们需要创建将存储所有语言环境文件的目录,每个语言环境一个。它们必须符合格式./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.
You need to decide on a text domain to use. This can be anything you want, but the script will look for a file called {yourTextDomain}.mo
within the LC_MESSAGES folder for that language. Put the following in your PHP script:
您需要决定要使用的文本域。这可以是您想要的任何内容,但脚本将查找{yourTextDomain}.mo
在 LC_MESSAGES 文件夹中为该语言调用的文件。将以下内容放入您的 PHP 脚本中:
define('TEXT_DOMAIN', 'yourdomain');
bindtextdomain(TEXT_DOMAIN, __DIR__.'/locale');
textdomain(TEXT_DOMAIN);
bind_textdomain_codeset(TEXT_DOMAIN, 'UTF-8');
Then to actually switch to another locale, do:
然后要实际切换到另一个语言环境,请执行以下操作:
$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));
Initially, you send the .pot
file generated by the script above to the translators. They then open Poedit and click on File > New from POT/PO file
. When they save it, they need to save it as {yourTextDomain}.po
. The {yourTextDomain}
needs to be exactly the same as the text domain you have in your PHP script. When they save it, it will automatically create both the .po
file and the .mo
file. Both of these need to be saved in that language's LC_MESSAGES
directory when they are done translating.
最初,您将上述.pot
脚本生成的文件发送给翻译人员。然后他们打开 Poedit 并单击File > New from POT/PO file
。当他们保存它时,他们需要将它保存为{yourTextDomain}.po
. 该{yourTextDomain}
需求是完全一样的,你在你的PHP脚本有文本域。当他们保存它时,它会自动创建.po
文件和.mo
文件。LC_MESSAGES
完成翻译后,这两个都需要保存在该语言的目录中。
Now when you update the strings in your PHP file, just re-execute the shell script and send the newly updated .po
files to the translators. They then translate the strings and both the .po
and .mo
files need to be re-uploaded.
现在,当您更新 PHP 文件中的字符串时,只需重新执行 shell 脚本并将新更新的.po
文件发送给翻译人员即可。然后他们翻译字符串,.po
并且.mo
需要重新上传和文件。
That's it. It may seem slightly difficult to get set up, but once you have it up and running, it's really easy.
就是这样。设置起来似乎有些困难,但是一旦启动并运行起来,就真的很容易了。
回答by grunk
Gettext seems to be what you need. There is a file by langage (except for the original one) and it's very easy to use :
Gettext 似乎是您所需要的。有一个语言文件(原始文件除外),并且非常易于使用:
echo _('Bonjour, ?a va ?');
will print Hello , how are you ? in english.
会打印你好,你好吗?用英语。
There is some toolswith gettext that could scan your php file and search for translatable string (in fact all string in _() or gettext()). Thanks to that you don't have to worry about the different langage file. You just code your website in the original langage and the langage file will automatically created later.
有一些带有 gettext 的工具可以扫描您的 php 文件并搜索可翻译的字符串(实际上是 _() 或 gettext() 中的所有字符串)。多亏了这一点,您不必担心不同的语言文件。您只需使用原始语言对您的网站进行编码,稍后将自动创建语言文件。
Nevertheless gettext is more a translation tools whereas intl is really an i18n one (number formating for example)
尽管如此,gettext 更像是一种翻译工具,而 intl 实际上是一个 i18n 工具(例如数字格式)
回答by andho
Althought you don't need a framework you can use a framework. The internationalization features in Zend Framework is pretty good and you can just use that part of it instead of using all the parts (including MVC)
虽然您不需要框架,但您可以使用框架。Zend Framework 中的国际化功能非常好,您可以只使用其中的一部分,而不是使用所有部分(包括 MVC)