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

2022-08-30 22:53:21

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

我没有没有框架的i18n经验,所以关于支持多语言的最简单方法的任何建议是什么?

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

=> en.yaml (yaml or not, it is example)

hello: "Hello world!"

=> fr.yaml

hello: "Bonjour tout le monde !"

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


答案 1

虽然 和 都与 i18(国际化)有关,但处理翻译,同时处理数字和日期显示、排序顺序和音译等国际化问题。因此,对于完整的i18解决方案,您实际上需要两者。根据您的需求,您可以根据上述扩展或某些框架提供的使用组件提出自制解决方案:ext/gettextext/intlgettextintl

如果您只需要翻译并且站点足够简单,也许您的简单解决方案(将翻译配置文件读取到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!');

答案 2

我知道这是一个老问题,但我觉得答案从头到尾都缺乏更实际的方法。这就是我所做的,通过使用PHP的gettextPoedit进行翻译,而无需在Debian服务器上使用任何其他PHP库:

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

我不确定其他操作系统是如何做到这一点的,但对于 Debian,你可以:

sudo apt-get install gettext
sudo dpkg-reconfigure locales

编辑:我以为Ubuntu会和Debian一样,但显然它略有不同。有关在 Ubuntu 上安装语言环境的说明,请参阅此页面

确保选择要使用的所有区域设置。然后,您应该看到类似下面的内容:

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-8es_ES.UTF-8es_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');

您可以将文本从更改为所需的任何内容,但必须在下面的shell脚本中对其进行更改。重要提示:翻译人员注释必须是函数前面行的注释的一部分,否则当我们扫描 PHP 文件以查找可翻译的字符串时,它不会被拾取。NOTE__()

// 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文件并创建一个文件(我称之为,但可以随意命名它),并使用新字符串更新它找到的任何现有文件。.poti18n.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文件夹中查找调用的文件。将以下内容放在 PHP 脚本中:{yourTextDomain}.mo

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));

最初,您将上述脚本生成的文件发送给转换器。然后,他们打开Poedit并单击。当他们保存它时,他们需要将其另存为 .需要与PHP脚本中的文本域完全相同。当他们保存它时,它将自动创建文件和文件。完成翻译后,这两者都需要保存在该语言的目录中。.potFile > New from POT/PO file{yourTextDomain}.po{yourTextDomain}.po.moLC_MESSAGES

现在,当您更新PHP文件中的字符串时,只需重新执行shell脚本并将新更新的文件发送给翻译人员即可。然后,他们翻译字符串,并且需要重新上传 和 文件。.po.po.mo

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


推荐