首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >国际化简单PHP网站的最佳方法

国际化简单PHP网站的最佳方法
EN

Stack Overflow用户
提问于 2011-08-05 08:34:55
回答 4查看 30.1K关注 0票数 18

我必须开发一个相当简单的php网站,所以我不需要框架。但它必须支持多种语言(EN/FR/CHINESE)。我已经查找了内置于系统中的php,并找到了两种方法:

  • 来自php5.3的intl模块(http://php.net/manual/fr/book.intl.php)
  • gettext (http://php.net/manual/fr/book.gettext.php)

在没有框架的情况下,我对i18n没有经验,所以对于支持多语言的最简单方法有什么建议吗?

最后,我只需要一个搜索翻译成文件的函数(一个文件一个语言)。情商:trans('hello');

=> en.yaml (yaml与否,这是一个例子)

代码语言:javascript
运行
复制
hello: "Hello world!"

=> fr.yaml

代码语言:javascript
运行
复制
hello: "Bonjour tout le monde !"

如果可能的话,我更喜欢纯PHP实现

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-08-05 09:22:02

虽然ext/gettextext/intl都与i18 (国际化)相关,但gettext负责翻译,而intl则处理诸如数字和日期显示、排序顺序和音译等国际化问题。所以你实际上需要两者同时完成i18的解决方案。根据您的需要,您可以根据上面提到的扩展或由某些框架提供的使用组件,提出一种家庭酿解决方案:

  • Internationalization
    • Zend Zend_Locale

如果您只需要翻译并且站点非常简单,那么您的简单解决方案(将翻译配置文件读入PHP数组,使用简单的函数检索令牌)可能是最简单的解决方案。

我能想到的最简单的解决方案是:

代码语言:javascript
运行
复制
$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!');
票数 24
EN

Stack Overflow用户

发布于 2015-07-02 05:39:57

我知道这是个老生常谈的问题,但我觉得答案从头到尾都缺乏一种更实际的方法。这就是我在不使用Debian服务器上的任何其他PHP库的情况下使用图书馆波编辑进行翻译时所做的:

准备步骤1:在服务器上安装gettext和区域设置

我不知道其他操作系统是如何做到这一点的,但是对于Debian,您可以这样做:

代码语言:javascript
运行
复制
sudo apt-get install gettext
sudo dpkg-reconfigure locales

编辑:我认为Ubuntu和Debian是一样的,但很明显,它略有不同。有关在Ubuntu上安装语言环境的说明,请参见此页

确保选择要使用的区域设置的all。然后,您应该看到如下内容:

代码语言:javascript
运行
复制
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-8es_MX.ISO-8859-1,它将无法工作。

准备步骤2:在翻译器的计算机上安装Poedit

Poedit可从大多数Linux操作系统的软件存储库中获得。对于基于Debian的,只需执行:

代码语言:javascript
运行
复制
sudo apt-get install poedit

对于Windows和Mac,请转到:https://poedit.net/download

开始编码:

好了,现在你准备开始编码了。我编写了以下gettext()包装函数来翻译单数和复数:

代码语言:javascript
运行
复制
function __($text, $plural=null, $number=null) {
    if (!isset($plural)) {
        return _($text);
    }
    return ngettext($text, $plural, $number);
}

示例用法:

代码语言:javascript
运行
复制
// 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的语言--这包括具有多种复数类型的语言。

您还可以添加如下所示的翻译注释:

代码语言:javascript
运行
复制
/** NOTE: The name Coconut Hotel is a brand name and shouldn't be 
 translated.
*/
echo __('Welcome to Coconut Hotel');

您可以将文本从NOTE更改为任何您想要的内容,但是您必须在下面的shell脚本中修改它。重要的:翻译器注释必须是函数前面的行注释的一部分,否则当我们扫描文件以寻找可翻译字符串时,它将不会被选中。

代码语言:javascript
运行
复制
// 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):

代码语言:javascript
运行
复制
#!/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

要执行它,只需做:

代码语言:javascript
运行
复制
cd /path/to/script && sh update.sh

这将递归地扫描该目录中的所有PHP文件,并创建一个.pot文件(我将其命名为i18n.pot,但可以随意命名),并用新字符串更新现有的.po文件。

然后,我们需要创建所有区域设置文件都将存储的目录,每个区域设置一个。它们必须是./locale/{locale}/LC_MESSAGES格式的。例如:

代码语言:javascript
运行
复制
cd /path/to/your/project
mkdir -p ./locale/en_US.UTF-8/LC_MESSAGES
mkdir -p ./locale/es_MX.UTF-8/LC_MESSAGES
# ...etc.

您需要决定要使用的文本域。这可以是您想要的任何内容,但是脚本将在该语言的{yourTextDomain}.mo文件夹中查找一个名为LC_MESSAGES的文件。将以下内容放在PHP脚本中:

代码语言:javascript
运行
复制
define('TEXT_DOMAIN', 'yourdomain');
bindtextdomain(TEXT_DOMAIN, __DIR__.'/locale');
textdomain(TEXT_DOMAIN);
bind_textdomain_codeset(TEXT_DOMAIN, 'UTF-8');

然后,要实际切换到另一个地区,请执行:

代码语言:javascript
运行
复制
$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文件都需要重新上传。

就这样。设置起来似乎有点困难,但是一旦你启动并运行了它,就真的很容易了。

票数 16
EN

Stack Overflow用户

发布于 2011-08-05 09:23:49

Gettext似乎是你所需要的。有一个按语言分类的文件(除了原始的文件),它非常容易使用:

代码语言:javascript
运行
复制
echo _('Bonjour, ça va ?');

会打印你好,你好吗?用英语。

带有gettext的一些工具可以扫描您的php文件并搜索可翻译的字符串(实际上,所有字符串都在_()或gettext()中)。由于这一点,您不必担心不同的语言文件。您只需编码您的网站在原来的语言和语言文件将自动创建以后。

然而,gettext更多的是一个翻译工具,而intl实际上是一个i18n工具(例如,生成数字)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6953528

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档