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

puruo6ea  于 2023-02-18  发布在  PHP
关注(0)|答案(4)|浏览(113)

我必须开发一个非常简单的PHP网站,所以我不需要框架。但它必须支持多种语言(英语/法语/中文)。我已经寻找PHP内置系统,我发现两种方法:

我在没有框架的i18 n方面没有经验,所以关于支持多语言的最简单的方法有什么建议吗?
最后,我只需要一个功能,搜索翻译成文件(一个文件的语言). EQ:trans('hello');
=〉en.yaml(不管是不是yaml,这是一个例子)

hello: "Hello world!"

=〉fr.yaml

hello: "Bonjour tout le monde !"

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

eivnm1vs

eivnm1vs1#

虽然ext/gettextext/intl都与i18相关(国际化),gettext处理翻译,而intl处理诸如数字和日期显示之类的国际化事物,排序顺序和音译。所以你实际上需要一个完整的i18解决方案。根据你的需要,你可能会想出一个家-brew解决方案依赖于上面提到的扩展或您使用的一些框架提供的组件:

*翻译

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

$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!');
ffscu2ro

ffscu2ro2#

我知道这是一个老问题,但我觉得答案从头到尾都缺乏一个更实际的方法。这就是我使用PHP's gettext libraryPoedit,而不使用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-8es_MX.ISO-8859-1,则无法正常工作。准备步骤2:在翻译人员的计算机上安装Poedit

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

sudo apt-get install poedit

对于Windows和Mac,请访问:https://poedit.net/download

开始编码:

好了,现在可以开始编写代码了,我编写了下面的gettext() Package 器函数来转换单数和复数:

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脚本(例如www.example.com)保存在应用程序的根目录中:update.sh) in your application's root directory:

#!/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. Please update the server's localisations.");
}
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文件都需要重新上传。
就是这样。设置起来可能看起来有点困难,但是一旦你设置好并运行起来,就真的很容易了。

vxf3dgd4

vxf3dgd43#

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

echo _('Bonjour, ça va ?');

会用英语打印你好吗。
some tools with gettext可以扫描你的php文件并搜索可翻译的字符串(事实上是_()或gettext()中的所有字符串).多亏了它,你不必担心不同语言的文件.你只需要用原来的语言编写你的网站,语言文件会在以后自动创建.
尽管如此,gettext更多的是一个翻译工具,而intl实际上是一个i18n工具(例如数字格式化)

brc7rcf0

brc7rcf04#

虽然你不需要框架,但你可以使用框架,Zend Framework的国际化特性非常好,你可以只使用它的一部分,而不是使用所有的部分(包括MVC)

相关问题