28

问题已更新,而不是提出新问题...

我真的很想在我正在建立的社交网站上提供一些除英语之外的其他语言,这将是我第一次做任何类型的语言翻译,所以请多多包涵。
我正在研究,所以我耳熟能详,对想法持开放态度,我已经有很多问题了。

1)
i18n是什么意思,我在SO上研究语言翻译时经常看到它?

2)
大多数人说使用gettext PHP有一个扩展或支持它,
我一直在研究它,我对它有一个基本的了解,据我所知,走这条路需要做很多额外的工作,
我意味着对我的网站进行编码以使用它的功能,即; _('hello world i'm in English for now')gettext('hello world i'm in English for now')没问题,因为我走的任何路线都需要这样做。
但是你必须在你的服务器上安装 gettext 并让它工作,
然后使用一些特殊的编辑器来创建特殊的文件并编译它们我认为?

听起来很痛苦,我知道这应该是最好的路线,但每个人似乎都这么说。
那么有人可以告诉我为什么这是要走的路吗?

3)
我真的很喜欢这种方法的简单性,只需构建一个语言数组并在函数中调用您需要的短语,如下例所示,然后您只需包含一个具有适当语言数组的文件。

我真正想知道的是,与使用 gettext 相比,在高流量和相当大的网站上,这是不是更好的性能方法,如果是这样,你能解释一下为什么吗?

<?PHP
//Have seperate language files for each language I add, this would be english file
function lang($phrase){
    static $lang = array(
        'NO_PHOTO' => 'No photo\'s available',
        'NEW_MEMBER' => 'This user is new'
    );
    return $lang[$phrase];
}
//Then in application where there is text from the site and not from users I would do something like this
echo lang('NO_PHOTO');  // No photo's available would show here
?>

* 下面的 brianreavis 回答中使用的一些代码

4

9 回答 9

24

最好定义一个处理语言映射的函数。这样,如果您以后确实想更改它的工作方式,您不必被迫搜索数百个脚本以查找您使用的情况$lang[...]并用其他东西替换它们。

像这样的东西会起作用,而且会很好&快速:

function lang($phrase){
    static $lang = array(
        'NO_PHOTO' => 'No photo\'s available',
        'NEW_MEMBER' => 'This user is new'
    );
    return $lang[$phrase];
}

确保数组是在函数内部声明static,这样每次调用函数时都不会重新分配它。$lang当非常大时,这一点尤其重要。

要使用它:

echo lang('NO_PHOTO');

要处理多种语言,只需在多个文件(如en.phpfr.php等)中定义此函数并require()为用户定义适当的函数。

于 2009-09-12T03:07:13.143 回答
11

这可能会更好:

function _L($phrase){
static $_L = array(
    'NO_PHOTO' => 'No photo\'s available',
    'NEW_MEMBER' => 'This user is new'
);

     return (!array_key_exists($phrase,$_L)) ? $phrase : $_L[$phrase];
}

这就是我现在使用的。如果找不到该语言,它将返回短语,而不是错误。

您应该注意,一个数组最多可以包含 ~65500 个项目。应该够了,但很好,只是说。

这是我用来检查用户语言的一些代码:

<?php
function setSessionLanguageToDefault() {
    $ip=$_SERVER['REMOTE_ADDR'];
    $url='http://api.hostip.info/get_html.php?ip='.$ip;
    $data=file_get_contents($url);
    $s=explode (':',$data);
    $s2=explode('(',$s[1]);

    $country=str_replace(')','',substr($s2[1], 0, 3));

    if ($country=='us') {
        $country='en';
    }

    $country=strtolower(ereg_replace("[^A-Za-z0-9]", "", $country ));
    $_SESSION["_LANGUAGE"]=$country;
}

if (!isset($_SESSION["_LANGUAGE"])) {
    setSessionLanguageToDefault();
}

if (file_exists(APP_DIR.'/language/'.$_SESSION["_LANGUAGE"].'.php')) {
    include(APP_DIR.'/language/'.$_SESSION["_LANGUAGE"].'.php');
} else {
    include(APP_DIR.'/language/'.DEFAULT_LANG.'.php');
}

?>

它还没有完成,但我认为这可能会有很大帮助。

于 2012-03-24T17:48:51.930 回答
7

不要编写自己的语言框架。使用gettext。PHP 具有可以安装的标准绑定。

于 2009-09-12T03:02:39.350 回答
4

不要重新发明轮子。例如使用gettextZend_Translate

于 2009-09-12T03:17:15.230 回答
2

由于其他答案并不能真正回答所有问题,因此我将在我的答案中提出这一点,并提供一个明智的选择。

1) I18n 是 Internationalization 的缩写,与 I-18-n 有一些相似之处。

2)老实说,gettext 是浪费时间。

3)你的方法看起来不错。您应该寻找的是语言变量。WoltLab Community Framework 2.0实现了双向语言系统。一旦有语言变量保存在数据库和模板中,只使用变量的名称,然后将替换为当前语言的变量内容(如果可用)。系统的第二部分提供了一种以多种语言保存用户生成的内容的方法(需要以多种语言输入)。

基本上,您拥有开发人员定义的界面文本和用户定义的内容。内容的多语言文本保存在语言变量中,然后将语言变量的名称用作特定内容表中文本字段的值(因为也可以使用单语言内容)。

遗憾的是,WCF 的结构在某种程度上重用框架之外的代码非常困难,但您可以将其用作灵感。系统的范围完全取决于您希望通过您的网站实现的目标。如果它比你要大,你绝对应该看看 WCF 系统。如果它很小,则可以使用一些专用语言文件(de.php、en.php 等),其中包含当前语言的正确文件。

于 2014-01-12T18:20:03.380 回答
1

为什么不把它做成多维数组……比如这个

<?php

$lang = array(
    'EN'=> array(
        'NO_PHOTO'=>'No photo\'s avaiable',
        'NEW_MEMBER'=>'This user is new',
    ),
    'MY'=> array(
        'NO_PHOTO'=>'Tiada gambar',
        'NEW_MEMBER'=>'Ini adalah pengguna baru',
    )
);

?>
于 2009-09-12T03:04:08.443 回答
1

你可以这样做:

class T {
const language = "English";
const home = "Home";
const blog = "Blog";
const forum = "Forum";
const contact = "Support";
}

对于每种语言,您都会有一个这样的文件。要使用文本:

There is no place like <?=T::home?>.

不利的一面是,如果您添加一个新常量,则必须为每个语言文件都这样做。如果您忘记了其中一个,您的分页会因该语言而中断。这有点讨厌,但它很有效,因为它不需要创建一个大的关联数组,甚至可能值会被内联。

也许可以改善访问,例如:

class T {
    const home = "home";

    public static function _ ($name) {
        $value = @constant("self::$name");
        return $value ? $value : $name;
    }

    // Or maybe through an instance:
    public function __get ($name) {
        $value = @constant("self::$name");
        return $value ? $value : $name;
    }
}
echo "There is no " . T::_("place") . " like " . T::_("home");
$T = new T();
echo "There is no " . $T->place . " like " . $T->home;

我们仍然避免使用数组并依靠常量来进行查找,我认为这比直接使用常量更昂贵。好的一面是查找可以在找不到键时使用回退。

于 2018-01-13T21:23:28.707 回答
1

对以上值得称赞的答案的扩展-我只是发布,因为也许这对最终来到这里的其他人也有用。

我个人更喜欢数组的键是我母语(在我的情况下是英语)中的实际短语,而不是 CONSTANT_VALUE,因为:

  • 当文本是我的母语时,我发现阅读代码更容易,而不必记住 CONSTANT_VALUE 实际输出的内容
  • 这意味着不需要查找来为也使用我的母语的访问者返回短语(提供稍微更好的性能)
  • 这是要维护的更少的价值列表

缺点是很难发现其他语言中的缺失值,因为您不再需要主列表 - 我还记录了抽象方法的警告,以便我发现任何缺失值。

我实现为:

  • 具有用于输出文本值的静态方法的抽象类(使用后期静态绑定)
  • 每种语言的具体类:英语覆盖返回短语而不翻译的方法,其他语言覆盖短语列表以便返回翻译后的短语
    <?php
    namespace Language;

    abstract class _Language
    {
        protected static $displayText = array();

        public static function output($phrase){
            return static::$displayText[$phrase] ?? $phrase;
        }
    }
    <?php
    namespace Language;

    class English extends _Language
    {
        public static function output($phrase){
            return $phrase;
        }
    }
    <?php
    namespace Language;

    class Spanish extends _Language
    {
        protected static $displayText = array(
            'Forename' => 'Nombre',
            'Registered Email' => 'Correo electrónico registrado',
            'Surname' => 'Apellido'
        );
    }

用法:

    $language = new \Language\Spanish();
    echo $language::output('Forename'); // Outputs: Nombre
    $language = new \Language\English();
    echo $language::output('Registered Email'); // Outputs: Registered Email
于 2020-03-29T22:30:34.233 回答
0

不幸的是, gettext不能很好地工作,并且在不同的操作系统(Windows 或 Linux)上等各种情况下都会出现问题,使其工作非常困难。

此外,它需要您设置很多环境变量和域,这没有任何意义。

如果开发人员想要简单地获取文本的翻译,他应该只设置 .mo 文件路径并使用诸如 translate("hello","en_EN"); 之类的一个函数来获取翻译。使用 gettext 这是不可能的。

于 2017-10-02T15:10:09.983 回答