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

ale*_*teg 25 php mysql performance multilingual gettext

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

  1. Gettext的与代.po文件功能
  2. 一个带有翻译的MySQL表和每个文本的唯一字符串ID
  3. 包含具有唯一字符串ID的不同翻译的数组的PHP文件

据我所知,Gettext函数应该是最有效的,但我的要求是应该可以更改原始参考语言(英语)中的文本字符串,而不会将该字符串的其他翻译自动恢复为英语只是因为几句话改变了.Gettext可以实现吗?

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

Ale*_*lec 26

一些注意事项:

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

msgid "A string to be translated would go here"  
msgstr ""
Run Code Online (Sandbox Code Playgroud)

现在,对于需要翻译它的人来说,这看起来很好并且可以理解.但是当你使用关键词时会发生什么,比如迈克建议的,而不是完整的句子?如果有人需要翻译一个名为"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");
Run Code Online (Sandbox Code Playgroud)

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

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


另一种选择:结合你的第二和第三种选择:

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

  1. 将变量添加到数据库(例如:id,page,variable);
  2. 为这些变量添加翻译(例如:id,varId,language,translation);
  3. 选择相关变量和翻译,将它们写入文件;
  4. 在您的网站中包含相关语言文件;
  5. 创建自己的函数来显示变量文本:

text('var'); 或者类似的东西 __('faq','register','lost_password_text');

第3点可以简单到从数据库中选择所有相关变量和转换,将它们放入数组并将serlialized数组写入文件.

好处:

  1. 保养.对于大型项目,维护文本可以更容易.您可以通过向数据库添加一列来定义此变量所属站点的哪一部分,按页面,部分或站点内的其他部分对变量进行分组.这样,您可以快速提取例如FAQ页面中使用的所有变量的列表.

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

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

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


ale*_*teg 13

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

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

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

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

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