我正在开发一个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。
答案 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_Locale
与Zend_Translate
结合使用。
Zend_Locale
可让您轻松检测用户的区域设置,或根据需要进行设置。例如,此类对于自动设置正确的货币格式非常有用。
Zend_Translate
可让您使用多个不同的formats轻松翻译文字:
答案 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);