编程多语言PHP应用程序

时间:2009-01-16 15:12:38

标签: php web-applications internationalization

我正在开发一个PHP应用程序,我想知道为其他国家/地区的用户提供多语言支持的最佳方式。

我精通PHP,但从未开发过任何支持其他语言的东西。

我正在考虑将语言放入带有常量的PHP文件中,例如:

en.php可能包含:

define('HZ_DB_CONN_ERR', 'There was an error connecting to the database.');

和fr.php可能包含:

define('HZ_DB_CONN_ERR', 'whatever the french is for the above...');

然后我可以调用一个函数并自动传入正确的语言。

hz_die('HZ_DB_CONN_ERR', $this);

这是一个很好的方式吗?

- morristhebear。

10 个答案:

答案 0 :(得分:11)

怪异。人们似乎忽略了明显的解决方案。您对区域设置特定文件的想法很好。有en.php:

define('LOGIN_INCORRECT','Your login details are incorrect.');
...

然后,假设你有一个全局配置/常量文件(由于很多原因我建议),请使用以下代码:

if ($language == 'en') {
  reqire_once 'en.php';
} else if ($language == 'de') {
  require_once 'de.php';
}

您可以定义数字和货币显示功能,比较/排序(即德语,法语和英语都有不同的校对方法)等。

人们常常忘记PHP是一种动态语言,所以这样的事情:

if ($language == 'en') {
  function cmp($a, $b) { ... }
} else if ($language == 'de') {
  function cmp($a, $b) { ... }
}

实际上是完全合法的。使用它们。

答案 1 :(得分:8)

您可以使用gettext或支持gettext的内容以及更多内容,例如Zend_Translate

编辑:

为了精确,Zend_Translate支持没有gettext模块的gettext。你可以在这里看到the many different types of input it supports

如果你也建议使用数组,你也可以使用Zend_Translate。关键是,如果你今天使用数组和明天的gettext,xml或其他东西,你只需要更改Zend_Translate的配置。

答案 2 :(得分:3)

我真的很喜欢以下方法:

一个文件是翻译器本身:

class Translator{
    private static $strs = array();
    private static $currlang = 'en';

    public static function loadTranslation($lang, $strs){
        if (empty(self::$strs[$lang]))
            self::$strs[$lang] = array();

        self::$strs[$lang] = array_merge(self::$strs[$lang], $strs);        
    }

    public static function setDefaultLang($lang){
        self::$currlang = $lang;        
    }

    public static function translate($key, $lang=""){
        if ($lang == "") $lang = self::$currlang;
        $str = self::$strs[$lang][$key];
        if (empty($str)){
            $str = "$lang.$key";            
        } 
        return $str;       
    }    

    public static function freeUnused(){
        foreach(self::$strs as $lang => $data){
            if ($lang != self::$currlang){
                $lstr = self::$strs[$lang]['langname'];
                self::$strs[$lang] = array();
                self::$strs[$lang]['langname'] = $lstr;                
            }            
        }        
    }

    public static function getLangList(){
        $list = array();
        foreach(self::$strs as $lang => $data){
            $h['name'] = $lang;
            $h['desc'] = self::$strs[$lang]['langname'];
            $h['current'] = $lang == self::$currlang;
            $list[] = $h;
        }
        return $list;        
    }

    public static function &getAllStrings($lang){
        return self::$strs[$lang];
    }

}

function generateTemplateStrings($arr){
    $trans = array();
    foreach($arr as $totrans){
        $trans[$totrans] = Translator::translate($totrans);
    }
    return $trans;    
}

语言文件可以只是include() d,如下所示:

en.php:

Translator::loadTranslation('en', array(
  'textfield_1'          => 'This is some Textfield',
  'another_textfield '   => 'This is a longer Text showing how this is used',
));

de.php:

Translator::loadTranslation('de', array(
  'textfield_1'          => 'Dies ist ein Textfeld',
  'another_textfield '   => 'Dies ist ein längerer Text, welcher aufzeigt, wie das hier funktioniert.',
));

在您的应用中,您可以翻译一个字符串,如下所示:

$string = Translator::translate('textfield_1')

甚至是一堆字符串:

$strings = generateTemplateStrings(array('textfield_1', 'another_textfield'));

因为可以只包含语言文件,所以你可以很容易地堆叠,比如先包含一个全局文件,然后包含子模块中的文件,这些文件可以添加新的字符串或替换已定义的字符串(不是使用define() - 方法)。

因为它是纯PHP,所以它甚至可以非常容易地进行操作码缓存。

我甚至有脚本生成包含文件中未翻译字符串的CSV文件,甚至更好:将翻译后的CSV文件转换回语言文件。

自2004年以来,我已将此解决方案用于生产用途,我对此非常满意。

当然,您甚至可以使用例如多元化的约定来扩展它。本地化数字格式是你必须使用其他方法做的事情 - 想到intl-extension。

答案 3 :(得分:3)

感谢所有人为您的方法和解决方案。我带着同样令人怀疑的问题来到这里,并且我可以肯定,使用“定义方法”更加真实,因为即使是奇怪的问题,不使用非常时尚的方法与其他库或一些,是现实的和在一个富有成效的思维中,很容易保持和理解,所以,你可以通过非编程技能得到其他语言。

我认为数组方法更好,因为你不需要分发那么大的多语言来获得一些转换,此外,你只使用较少的内存,因为你只加载了所需的被转换的字符串。

关于那些不能重新定义的东西;好吧,一般来说,如果你定义常量是因为它们不需要或不必更改,所以如果需要你可以使用一个部分来定义字符串和变量。

我补充一点,我不喜欢这些定义文件的外观,但是,请记住,访问者并不担心成语实现的方式,是一个完美有效的实现,你可以很容易地得到一些TRADUCTIONS。

答案 4 :(得分:2)

您可能希望查看像CakePHP或CodeIgniter这样的框架,这使得编写国际化应用程序变得更加容易。这不仅仅是你必须考虑的字符串 - 数字格式和日期格式之类的东西也必须考虑到

答案 5 :(得分:2)

只要解决方案仅用于翻译,您的解决方案就可以正常工作。正如其他人所提到的,还有许多其他基于区域设置的变量,例如货币和日期格式。

使您的应用程序区分设置的可靠方法是将Zend_LocaleZend_Translate结合使用。

Zend_Locale 可让您轻松检测用户的区域设置,或根据需要进行设置。例如,此类对于自动设置正确的货币格式非常有用。

Zend_Translate 可让您使用多个不同的formats轻松翻译文字:

  • 阵列
  • CSV
  • Gettext的
  • 的Ini
  • TBX
  • TMX
  • Qt的
  • XLIFF
  • XmlTm

答案 6 :(得分:0)

如果根据用户选择的语言包含不同的常量文件,您的方法是可行的。

你也可以跳过常量部分,然后用constant =>定义一个大的哈希表。转换以防止命名空间崩溃。

file:en.php

$constants = Array(
 'CONSTANT_KEY' => 'Translated string'
);

file:functions.php

function getConstant($key, $fallback) {
   // ... return constant or fallback here.
}

然而,当涉及到大量数据时,这种方法很难维护。还有一些其他方法可以更好地满足您的目的,例如,一个理想的解决方案是将所有常量存储在整个站点的全局memoryspace中,以避免让每个reguest / thread保留所有这些翻译后的数据记忆。这需要一些php模块方法。像这里的人建议的Gettext可能会使用这种方法。

Google for PHP本地化以寻找有用的资源。

答案 7 :(得分:0)

一个提示,就是创建一个返回已翻译字符串的函数,如果它不在哈希表中,则返回您请求的哈希键,并在其后面添加*,以通知您需要翻译。 / p>

答案 8 :(得分:0)

我是这样做的:

parent_script.php:

$lang_pick = "EN";    //use your own method to set language choice

require_once('trans_index.php'); 

echo $txt['hello'];

trans_index.php:

    $text = array();

    $text['hello'] = array (
     "EN"=> "Hello",
     "FR"=> "Bonjour",
     "DE"=> "Guten Tag",
     "IT"=> "Ciao"
    );                          //as many as needed



foreach($text as $key => $val) {

$txt[$key] = $text[$key][$lang_pick];

}

这可能对您的需求来说太简单了,但我发现它非常可行。它还可以很容易地维护文本的多个版本。

答案 9 :(得分:0)

您可以使用我喜欢的语言PHP Multi Language Class - LangQuery

这是我见过的最容易的。

您可以将语言数据保存到.ini文件,而不仅仅是通过

调用它
include("LangQuery.php");

$L=new LangQuery();

// Write Hello World
echo($L('hello_world'));

// Write Hello World Easier - In-line Echo Feature
// You don't have to write echo. Just add '>'
$L('>hello_world');

// Use in Strings
echo("Hello Universe. {$L('hello_world')} Hello Europe");

// Write my age with parameter
$L(">my_age",25);

// Write my name and age with parameters
$L(">my_name_age","Recep",25);