【发布时间】:2011-01-30 00:56:20
【问题描述】:
谁能告诉我如何用 PHP 和 MySQL 制作动态多语言网站?我对此一无所知。我在谷歌上搜索并没有找到任何好的解决方案。
任何人都可以为我提供分步指南吗?如果可能,为多语言网站制作演示。或者请参考任何链接,其中解释了有关它的详细信息。
【问题讨论】:
标签: php mysql internationalization multilingual
谁能告诉我如何用 PHP 和 MySQL 制作动态多语言网站?我对此一无所知。我在谷歌上搜索并没有找到任何好的解决方案。
任何人都可以为我提供分步指南吗?如果可能,为多语言网站制作演示。或者请参考任何链接,其中解释了有关它的详细信息。
【问题讨论】:
标签: php mysql internationalization multilingual
简答:没有简答,因为有很多变量需要考虑,还有很多工作要做。所以……
长答案:我将尽我所能分解它,但对于像你这样广泛的问题,没有一个“对所有人都有好处”的答案。
首先,手头任务的变量:
语言列表:您的网站会使用预定义的语言集,还是会变化/异类?例如,一个网站可能完全是两种定义明确的语言的双语(或者,再举一个例子,我经营一个英语/加泰罗尼亚语/西班牙语网站);或者可以在不同的语言集上提供不同的部分(例如,查看 MS 的网站:它们大多是同质的,但博客、知识库文章和某些文档等内容仅以所谓的支持语言的子集提供)。
翻译来源:每种相关语言的内容是由您还是某个合作者提供的?还是某些版本通过翻译软件从单一“基础”语言运行?第一种方法需要大量额外的工作来生成内容,但比第二种方法产生的结果质量更高。
语言本身:一旦您回答了 1) 和 2),您将需要确切了解您正在使用哪些语言。请注意,如果您包含方言(例如:美国英语 + 英国英语,或阿根廷西班牙语 + 西班牙西班牙语),您可能会在搜索引擎中遇到一些“重复内容”问题,但这里的详细信息太离题了(只是提及以便您了解潜在问题)。
您是否针对抽象语言(例如,我的网站提供三种语言而完全不关心访问者在哪里:这就是我所拥有的,所以选择您喜欢的语言);还是针对不同的地区/国家?在后一种情况下,事情可能会变得更加复杂,因为您可能需要关心除语言之外的其他内容(例如时区、货币或日期时间格式约定等),但您可以获得能够使用的好处特定国家/地区的 TLD。
一旦您对上述内容进行了明确定义,就可以开始工作了。这些是您需要处理的最突出的任务:
语言检测:最合理的方法是使用 GET 参数(类似于 URL 上的 ?lang=en-us)。此外,当请求没有语言参数的 URL 时,您可能会使用一些 cookie 和/或 IP 地理位置来回退。另外,如果你有办法,可以考虑 URL 美化这个话题(哪个更好看:example.com/index.php?lang=en-us 或 example.com/en-us/home?)。就我个人而言,我喜欢 ModRewrite 授予我的 .htaccess 文件的功能,但这仅适用于 Apache 驱动的服务器。
内容管理:无论您是从数据库中获取内容(如文章内容)、包含文件(通常用于面包屑、菜单、站点范围的标题等),还是任何其他方式,您都需要一些方法来将内容的每个版本(语言)分开。以下是一些如何实现的示例:
_en、_es 或_ca 附加到我的数据库的所有语言相关字段。这样,我可以使用$row["title_$lang"] 等表达式访问正确的内容。.en.php、.ca.htm 等结尾。我的包含调用看起来像include("some-filename.$lang.php)。语言选择:非常重要,除了调整 URL 本身的 GET 参数之外,您应该为用户提供一种选择自己语言的方法。对于少数语言,“标志”通常效果很好,因为即使页面最初退回到用户根本不知道的语言,它们也可以被理解。对于更多语言,下拉菜单似乎更有效(就视口空间而言),但您应该确保添加一些视觉(即:非文本)提示。有些网站会强制您在输入时选择一种语言,并且每种语言只有指向主页的链接。就我个人而言,我的三个标志位于站点菜单的顶部,每个都指向当前地址,只更改了语言参数。像这样的代码可以很好地工作:
function translatedURI($new_lang) {
return str_replace("lang=$lang", "lang=$new_lang", "http://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
}
嗯,这就是我现在能想到的一切。我认为你应该有足够的时间挽起袖子开始工作。然后,如果您在前进的道路上碰壁,请回来提出具体问题,我相信您会得到更具体的答案。
希望这会有所帮助。
【讨论】:
我一直使用的解决方案是创建一个包含所有可能消息的数据库表。对于每条消息,我使用一个代码(缩写)来查找它。比如:
lang id message
en login Login
en lostpass Lost your password?
de login Anmelden
de lostpass Paswort vergessen?
nl login Aanmelden
nl lostpass Wachtwoord vergeten?
等等。使用 MySQL 查询查找翻译通常足够快,但您也可以将所有消息放在一个数组中,并在脚本加载时将其加载到内存中。用户应该始终能够设置他们喜欢的语言,不要盲目依赖网络浏览器设置的语言头。
【讨论】:
SELECT * FROM ... WHERE file = 'filename.php'。循环遍历每个结果行,然后将翻译添加到常量或数组,或者您正在处理的语言。这也将阻止“100 多个 SQL 查找的可能性”。
我现在正在设计一个非常小的 CMS,它必须是多语言的。
我最关心的功能之一是客户可以自发地决定添加或删除一种语言。
出于这个原因,我的目标不是为数据库表添加后缀,我不能(也不想)修改表名或使用动态名称访问它们,也不能在每次使用语言时添加或删除字段定义或删除。
我也不会使用文件,只是因为我喜欢数据库并且它们易于维护。
最后,我认为有两种翻译:
因此,我的设计旨在:
这意味着在单语言场景中哪些字段将具有内容的表现在将其内容无效,因为它将始终在翻译表中。
这会增加 SQL 查询的复杂性,但它允许我开发工具来以简单的方式维护翻译。此外,SQL 的复杂性只存在一次,就在实施解决方案时。如果该实施设计得当,网站的维护/可扩展性就不会成为主要问题。
编辑:
在与开发者朋友交谈后,我认为我在这里接近的解决方案在单张桌子上收费过高。
我将从现在开始研究的另一种方法是为每个“可翻译表”创建一个额外的表,如下所示:
此方案继承了第一个方案的概念,但将每个表格的内容分开。这种替代解决方案可能会提高性能并隔离问题(作为索引问题)。
每个“可翻译表”的额外翻译表将与原始翻译表同时创建。
关于SQL查询,复杂度还是一样的:第一种方法需要表名来搜索translations表,而第二种方法只是在表名后面加上后缀“_translations”。
【讨论】: