多语言PHP网站最有效的方法

时间:2010-05-10 22:28:18

标签: php mysql performance multilingual gettext

我正在建立一个大型多语种网站,我正在考虑采用不同的方法使其多语言化。我能想到的可能的替代方案是:

  1. 生成.po文件的Gettext函数
  2. 一个包含翻译的MySQL表和每个文本的唯一字符串ID
  3. 包含具有唯一字符串ID的不同翻译的数组的PHP文件
  4. 据我所知,Gettext函数应该是最有效的,但我的要求是应该可以更改原始参考语言(英语)中的文本字符串,而不会将该字符串的其他翻译自动恢复为英语只因为几个词改变了。这可以用Gettext吗?

    资源要求最低的解决方案是什么? 使用Gettext函数或PHP文件与数组或多或少同等资源要求? 有关更有效解决方案的任何其他建议吗?

3 个答案:

答案 0 :(得分:26)

一些注意事项:

<强> 1。翻译
谁将进行翻译?那些也与网站相关的人?翻译机构?使用Gettext时,您将使用'pot'(。po)文件。这些文件包含消息ID和消息字符串(转换)。例如:

msgid "A string to be translated would go here"  
msgstr ""

现在,对于需要翻译此功能的人来说,这看起来很好,也很容易理解。但是当你使用关键词时会发生什么,比如迈克建议的,而不是完整的句子?如果有人需要翻译一个名为“address_home”的msgid,他或她就不知道这应该是一个标题“Home address”还是一个完整的句子。在这种情况下,请确保在调用gettext函数之前立即向文件添加注释,如下所示:

/// This is a comment that will be included in the pot file for the translators
gettext("ready_for_lost_episode");

在创建.po文件时使用xgettext --add-comments=///将添加这些注释。但是,我不认为Gettext是以这种方式使用的。此外,如果您需要添加带有每个文本的注释,那么您可能会在某些时候出错,b)您的整个脚本无论如何都将填充文本,只有在评论形式中,c)评论需要直接放在Gettext函数的上面,这取决于代码中函数的位置,并不总是很方便。

<强> 2。维护
一旦您的网站(甚至更远)和您的语言文件一起增长,可能很难以这种方式维护所有不同的翻译。每次添加文本时,都需要创建新文件,将文件发送给翻译人员,接收文件,确保结构仍然完整(渴望翻译人员也乐于翻译语法,制作整个文件无法使用:)),并完成导入新翻译。这是可行的,当然,但要注意大型网站和许多不同语言的可能问题。

<小时/> 另一种选择:结合您的第二和第三种选择:

就个人而言,我发现使用(简单)CMS管理翻译更有用,将变量和翻译保存在数据库中并自己将相关文本导出到语言文件中:

  1. 将变量添加到数据库中(例如:id,page,variable);
  2. 为这些变量添加翻译(例如:id,varId,language,translation);
  3. 选择相关变量和翻译,将其写入文件;
  4. 在您的网站中包含相关语言文件;
  5. 创建自己的函数以显示变量文本:
  6. text('var');或类似__('faq','register','lost_password_text');

    之类的内容

    第3点可以像从数据库中选择所有相关变量和翻译一样简单,将它们放入数组并将serlialized数组写入文件。

    优点:

    1. 维护。对于大型项目,维护文本可以更容易。您可以通过向数据库添加一列来定义此变量所属站点的哪一部分,按页面,部分或站点内的其他部分对变量进行分组。通过这种方式,您可以快速获取所有变量的列表,例如常见问题页面。

    2. 翻译。您可以在一个页面上显示包含所有不同语言的所有翻译的变量。这可能对那些可以同时将文本翻译成多种语言的人有用。查看其他翻译以了解上下文以使翻译尽可能好,这可能会很有用。您还可以查询数据库以查找已翻译的内容和未翻译的内容。也许添加时间戳来跟踪可能过时的翻译。

    3. 访问。这取决于谁将翻译。您可以通过简单的登录来包装CMS,以便在需要时向翻译机构的人员授予访问权限,并且只允许他们更改某些语言甚至网站的某些部分。如果这不是一个选项,您仍然可以将数据输出到可以手动翻译的文件并稍后导入(尽管这可能会出现与前面提到的相同的问题。)。您可以添加其中一个已经存在的翻译(英语或其他主要语言)作为翻译的上下文。

    4. 总而言之,我认为你会发现你可以通过这种方式更好地控制翻译,特别是从长远来看。与原生gettext函数相比,我无法告诉您有关此方法的速度或效率的任何信息。但是,根据语言文件的大小,我认为这不会是一个很大的区别。如果按页面或部分对变量进行分组,则可以始终只包含所需的部分。

答案 1 :(得分:13)

经过一些测试后,我终于决定采用Alecs的第二种和第三种替代品的组合。

Gettext问题
我试图首先设置整个gettext系统来尝试它,但事实证明它比我想象的要复杂得多。问题是Windows和Unix系统对setlocale()使用不同的语言短名称。目前我在Windows上使用Wamp运行我的开发服务器,而最终站点将在Linux上运行。在我完成了几个dozen guidesforumsquestions等操作后,每次修改后重新启动服务器。我似乎无法以任何简单的方式正确设置它。此外,gettext不是线程安全的,更新服务器需要重新启动的语言文件或需要使用a hack,没有简单的方法来处理不同版本的语言文件或处理原始英文文本而不修改源代码或使用Mikes建议,正如Alec指出的那样不是最佳的。

<强>解决方案
所以我最终得到了我认为是基于Alecs响应的最佳解决方案:

  • 使用字段保存数据库中的所有翻译; language,page,var_key,version,revision和last_modified_time - 其中版本对应于原始翻译的版本(英语),而修订允许翻译者修改/更正版本中的最终翻译。
  • 使用一种CMS进行翻译,它连接到数据库并处理不同的版本,并可以轻松概览翻译的语言,翻译版本和翻译的完整程度。
  • 当完成版本的修订时,会生成一个缓存文件 - 每个文件都包含一个数组,该数组只包含一种语言和一个页面的var_key和文本转换,并以ISO 639-1种语言的名称命名和页面名称如:lang / en_index.php然后简单地包含这些语言文件并将其包装在函数t($ var_key)中,该函数允许在开发期间使用DB,然后更改为仅使用缓存文件。

<强>性能
我从来没有去测试gettext,但是根据the link Mike posted,使用数组和gettext之间的性能差异对我来说完全可以接受,如上所述,自定义系统给出的好处。但是,与使用MySQL DB检索相同的20个文本字符串相比,我使用数组与数组中的20个翻译文本字符串进行比较。事实证明,使用文件中包含的数组比从MySQL数据库同时检索所有20个字符串 快6倍 。这不是真正的科学基准,结果可能会因不同的系统和设置而有所不同,但它清楚地显示了我的预期 - 使用数据库比直接使用数组要慢得多,这就是我选择生成缓存的原因 - 数组的文件而不是使用数据库。

作为比较,我还测试了仅输出具有相同文本的简单回声的速度。事实证明,它比使用包含文件中的数组快20倍左右,但是如果没有针对不同语言的页面的不同版本,则无法翻译,这违背了动态页面的目的。然后最好还使用a good cachesystem

性能测试源文件:
PHP:http://pastie.org/964082
MySQL表:http://pastie.org/964115
它肯定不是完美的,但至少可以创造一个关于性能差异的想法。

答案 2 :(得分:3)

您不必使用英文文本作为关键字,您可以任意执行此操作,但也提供英文翻译,即。

gettext键是'hello'

然后您可以使用这种语言的各种语言翻译,以及也是“hello”的英语翻译,然后如果您想更新字符串的英文版本,您可以单独保留密钥并更新英文翻译。