在PHP中保留依赖于区域设置的字符串资源的最佳方法?

在PHP中保留依赖于区域设置的字符串资源的最佳方法?,php,internationalization,Php,Internationalization,假设您正在构建一个多语言web应用程序,其中所有界面文本都应移动到依赖于语言的资源中,并在需要时加载。字符串资源可能是巨大的:假设您已经翻译了数千个字符串。在窗口环境(Windows、OS X、X11)中,通常有操作系统或某些API提供的机制来实现这一点,它们通常称为字符串资源。那么PHP呢 但请记住,在这里必须认真考虑性能,因为PHP会根据每个用户请求编译和执行所有模块 我可以想出几种可能的方法。但首先,我将有一个全局变量$LANGUAGE,可以设置为'en'、'de'、'fr'等。我将使用这

假设您正在构建一个多语言web应用程序,其中所有界面文本都应移动到依赖于语言的资源中,并在需要时加载。字符串资源可能是巨大的:假设您已经翻译了数千个字符串。在窗口环境(Windows、OS X、X11)中,通常有操作系统或某些API提供的机制来实现这一点,它们通常称为字符串资源。那么PHP呢

但请记住,在这里必须认真考虑性能,因为PHP会根据每个用户请求编译和执行所有模块

我可以想出几种可能的方法。但首先,我将有一个全局变量$LANGUAGE,可以设置为'en'、'de'、'fr'等。我将使用这个变量在每个请求中包含一个特定于语言的模块

require_once "lang-$LANGUAGE.inc.php"
因此,一些可能的解决方案包括:

(1) 在每个语言模块中将所有字符串定义为全局变量,例如

$str_signin = 'Sign in';
$str_welcome_user = 'Welcome, %s'!;
...
非常简单,易于阅读,并且对于非技术人员(即翻译人员)来说相对容易操作。不过,存在一些全局空间污染,这会稍微减慢全局变量查找的速度

(2) 相同,但定义为一个巨大数组,例如

$str['signin'] = 'Sign in';
$str['welcome_user'] = 'Welcome, %s'!;
...
在主代码中可读性差、可用性差(需要更多的键入)也会使代码更加混乱。这会更慢,因为这些不是简单的分配,而是关联的数组分配:与(1)相比,VM在这里要执行的指令更多

(3) PHP5.3+:定义为常量,可能在类或命名空间中

class str {
    const signin = 'Sign in';
    const welcome_user = 'Welcome, %s'!;
    const signin_to_a = self::signin . ' to area A'; // can't do this!
    ...
}
。。。并将它们用作str::sign等。很好,我最喜欢这个,尽管也有一些小缺点:仅PHP5.3+;不能使用表达式,只能使用单个值(在您的情况下,这可能没问题);不能在双引号字符串的$-扩展中使用(或者您可以?)

(4) 数据库:将所有内容放入一个表中,并通过一些ID进行检索,例如str_get(str_sign)。丑陋、缓慢,需要将代码中的ID与DB ID同步,但是当页面只需要几个字符串时,不需要加载所有内容。老实说,我不能说这是不是一个好的解决方案

还有其他建议吗?还有,关于这些问题的想法

请记住简洁、优雅和性能

那gettext呢?
或者,Zend Framework提供了一个非常可靠的接口来处理翻译。

Zend Framework有一个名为Zend_Translate的组件,该组件非常有用,并且可以通过不同的方式存储字符串,即使您决定不使用ZF组件

如果作为开发人员维护字符串,PHP是性能最好的解决方案。如果你在一家翻译公司工作,他们很可能希望与CSV合作,并来回发送这些信息


我不知道数组还是基于常量的解决方案更好,但我的钱在数组上。一个快速的基准测试很快就会告诉您。

我使用mysql表来存储所有语言字符串。这样我就可以轻松地创建一个用户界面来编辑它们。
我将与对象相关的所有语言字符串作为关联数组(使用ADODB中的GetAssoc函数)。我使用Pear::cache类缓存assoc数组,所以下次我将只检索这个缓存的数组(无数据库查询)。这是迄今为止对我来说最好的解决办法。这可以使用不同的缓存技术进行优化。

我对前三种方法进行了简单的基准测试。我创建了具有10000个字符串分配的模块,并分别测量了加载/编译时间和访问时间

毫不奇怪的是,与globals和array方法相比,常量的加载和编译速度要快得多。但令我惊讶的是,常数的访问速度要慢得多!可能是因为这是PHP中的一种新机制,尚未完善

此外,事实证明,庞大的数组比all-globals方法编译速度更快(事实上,数组(…)构造甚至更快),但是数组访问成本更高

考虑到您通常加载大量的区域设置数据,然后只使用其中的一小部分,我认为最明智的方法是常量。毫不奇怪,类静态常量比全局常量性能更好


所以我选择方法3。我还没有测试过数据库方法,但有人建议读取整个数据库表的成本与读取同一卷的PHP源代码的成本大致相同或更高。

密切相关:谢谢,我做了一些测试,并在此线程中发布了答案,以防您感兴趣。此方法可能听起来很慢,因为它包含“数据库访问“。但您只读取数据库一次,然后将结果存储在缓存文件中。缓存文件可以是包含数组或常量的PHP源,也可以是任何内容。过去我使用的是语言文件,但我无法为翻译人员提供接口,也无法轻松找到翻译字符串。我会选择方法2。Const访问速度很慢(正如我所怀疑的),您可以使用类似APC的东西来操作码缓存阵列文件。这跳过了“编译”步骤。然后您可以从快速访问中获益。