php Yii:多语言网站 - 最佳实践

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2497118/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 06:42:41  来源:igfitidea点击:

Yii: Multi-language website - best practices

phpinternationalizationyii

提问by migajek

I find Yii great framework, and the example website created with yiic shell is a good point to start... however it doesn't cover the topic of multi-language websites, unfortunately. The docs covers the topic of translating short messages, but not keeping the multi-lingual content ...

我发现 Yii 很棒的框架,使用 yiic shell 创建的示例网站是一个很好的起点……但是不幸的是,它没有涵盖多语言网站的主题。文档涵盖了翻译短消息的主题,但没有保留多语言内容......

I'm about to start working on a website which needs to be in at least two languages, and I'm wondering what is the best way to keep content for that ... The problem is that the content is mixed extensively with common elements (like embedded video files).

我即将开始在一个至少需要两种语言的网站上工作,我想知道保留内容的最佳方法是什么......问题是内容与常见元素广泛混合(如嵌入的视频文件)。

I need to avoid duplicating those commons ... so far I used to have an array of arrays containing texts (usually no more than 1-2 short paragraphs), then the view file was just rendering the text from an array.

我需要避免重复那些公共...到目前为止,我曾经有一个包含文本的数组数组(通常不超过 1-2 个短段落),然后视图文件只是从数组中渲染文本。

Now I'd like to avoid keeping it in arrays (which requires some attention when putting double quotations " " and is inconvenient in general...).

现在我想避免将它保留在数组中(这在放置双引号时需要注意“”,并且通常不方便......)。

So, what is the best way to keep those short paragraphs? Should I keep them in DB like (id | msg_id | language | content ) and then select them by msg_id & language? That still requires me to create some msg_id's and embed them into view file ...

那么,保留这些短段落的最佳方法是什么?我应该像 (id | msg_id | language | content ) 一样将它们保存在数据库中,然后通过 msg_id & language 选择它们吗?这仍然需要我创建一些 msg_id 并将它们嵌入到视图文件中......

Is there any recommended paradigm for which Yii has some solutions?

有没有推荐的范式,Yii 有一些解决方案?

Thanks, m.

谢谢,米。

采纳答案by edigu

A Yii application by default uses yii::t() method for translating text messages and there are 3 different types for message sources:

Yii 应用程序默认使用 yii::t() 方法来翻译文本消息,消息源有 3 种不同类型:

  1. CPhpMessageSource: Translations are stored as key-value pairs in a PHP array.
  2. CGettextMessageSource: Translations are stored as GNU Gettext files. (PO Files)
  3. CDbMessageSource: Message translations are stored in database tables.
  1. CPhpMessageSource:翻译作为键值对存储在 PHP 数组中。
  2. CGettextMessageSource:翻译存储为 GNU Gettext 文件。(采购订单文件)
  3. CDbMessageSource:消息翻译存储在数据库表中。

If i don't misunderstand, you are using classic arrays for translations. I recommend to you using GetText and PO files with Yii for translation operations.

如果我没有误解,您正在使用经典数组进行翻译。我建议你使用 GetText 和 PO 文件和 Yii 进行翻译操作。

You can find lot of information about translation and i18n with yii in this official documentation page.

你可以在这个官方文档页面中找到很多关于 yii 的翻译和 i18n 的信息。

回答by ianaré

Gettext is good for its ease of translation, but the default PHP implementation is not thread safe. Yii therefore uses its own unpacker, dramatically increasing processing time compared to php arrays.

Gettext 的优点是易于翻译,但默认的 PHP 实现不是线程安全的。因此,Yii 使用自己的解包器,与 php 数组相比,显着增加了处理时间。

Since I was setting up a high volume, high transaction site, the performance hit was not acceptable. Also, by using APC, we could cache the PHP translation further increasing performance.

由于我正在建立一个高容量、高交易量的站点,因此性能下降是不可接受的。此外,通过使用 APC,我们可以缓存 PHP 翻译,进一步提高性能。

My approach was therefore to use PHP arrays but to keep the translations in a DB for ease of translation, generating the needed files when translations are changed.

因此,我的方法是使用 PHP 数组,但将翻译保存在数据库中以便于翻译,在翻译更改时生成所需的文件。

The DB is similar to this :

数据库类似于:

TABLE Message            // stores source language, updated by script
 id INT UNSIGNED
 category VARCHAR(20)         // first argument to Yii::t()
 key TEXT                     // second argument to Yii::t()
 occurences TINYINT UNSIGNED  // number of times found in sources

TABLE MessageTranslation // stores target language, translated by human  
 id INT UNSIGNED
 language VARCHAR(3)          // ISO 639-1 or 639-3, as used by Yii
 messageId INT UNSIGNED       // foreign key on Message table
 value TEXT
 version VARCHAR(15)
 creationTime TIMESTAMP DEFAULT NOW()
 lastModifiedTime TIMESTAMP DEFAULT NULL
 lastModifiedUserId INT UNSIGNED

I then modified the CLI tool yiic 'message' command to dump the collected strings into the DB.

然后我修改了 CLI 工具 yiic 'message' 命令以将收集的字符串转储到数据库中。

http://www.yiiframework.com/wiki/41/how-to-extend-yiic-shell-commands/

http://www.yiiframework.com/wiki/41/how-to-extend-yiic-shell-commands/

Once in the DB, a simple CMS can be setup to provide translators an easy way to translate and at the same time providing versioning information, reverting to older versions, checking quality of translators, etc ...

一旦进入数据库,就可以设置一个简单的 CMS 为翻译人员提供一种简单的翻译方法,同时提供版本信息、恢复到旧版本、检查翻译人员的质量等......

Another script, also modified from yiic, then takes the DB info and compiles it into PHP arrays. Basically a JOIN of the two tables for each language, then build an array using 'Message'.'key' and 'MessageTranslation'.'value' as (what else?) key => value ... saving to file named from 'Message'.'category' in folder specified by language.

另一个脚本也是从 yiic 修改而来,然后获取 DB 信息并将其编译为 PHP 数组。基本上是每种语言的两个表的 JOIN,然后使用 'Message'.'key' 和 'MessageTranslation'.'value' 作为(还有什么?)key => value ... 保存到名为 from 的文件语言指定的文件夹中的消息'.'category'。

The generated files are loaded as normal by Yii CPhpMessageSource.

生成的文件由 Yii CPhpMessageSource 正常加载。

For images, this was as simple as placing them in folders with the proper language and getting the app language when linking.

对于图像,这就像将它们放在具有正确语言的文件夹中并在链接时获取应用程序语言一样简单。

<img src="/images/<?php echo Yii::app()->language; ?>/help_button.png">

Note that in real life, I wrote a little helper method to strip off the country from the language string, 'en_us' should be 'en'.

请注意,在现实生活中,我写了一个小助手方法来从语言字符串中剥离国家,'en_us' 应该是 'en'。

回答by user366852

Well I think what is concerned here is how to translate static text/messages on the page and Yii solves it pretty well using Yii:t() and Edigu's answer is for it.

好吧,我认为这里关心的是如何翻译页面上的静态文本/消息,Yii 使用 Yii:t() 很好地解决了这个问题,Edigu 的答案就是为此。

I check out the post on FlexicaCMS about translating dynamic content in database, well ultimately that will be the next after you solve static text/message problem, and that is a truly good approach using Yii's behavior. Not sure if FlexicaCMS authors are too ambitious in supporting translation that way as it would make content translation a worry-free thing - really great.

我查看了 FlexicaCMS 上关于翻译数据库中的动态内容的帖子,最终这将是您解决静态文本/消息问题后的下一个,这是使用 Yii 行为的真正好方法。不确定 FlexicaCMS 的作者是否在以这种方式支持翻译方面过于雄心勃勃,因为它会使内容翻译成为无忧无虑的事情 - 真的很棒。

One thing they don't mention is the url of translated page. For example your.site.com/fr/translated_article_title.html. I mean the url must has /language_id/ part in it so it can help with SEO.

他们没有提到的一件事是翻译页面的网址。例如 your.site.com/fr/translated_article_title.html。我的意思是 url 必须包含 /language_id/ 部分,以便它可以帮助 SEO。

回答by Alix

In Yii1 and Yii2 yii\i18n\GettextMessageSource doesn't use Yii perfect cache engine anyway (look at the source) to enhance the load of PO or MO files. It's not recommended to load these files by using php pure code (including yii\i18n\GettextMessageSource) (it's so slower than php array idx) : http://mel.melaxis.com/devblog/2006/04/10/benchmarking-php-localization-is-gettext-fast-enough/

在 Yii1 和 Yii2 中,yii\i18n\GettextMessageSource 无论如何都没有使用 Yii 完美的缓存引擎(查看源代码)来增强 PO 或 MO 文件的负载。不建议使用 php 纯代码(包括 yii\i18n\GettextMessageSource)加载这些文件(它比 php array idx 慢):http://mel.melaxis.com/devblog/2006/04/10/benchmarking- php-localization-is-gettext-fast-enough/

However php gettext ext for MO files is a few faster than translation php array because it uses cache but the negative point is : every change in MO requires server restart.

然而,用于 MO 文件的 php gettext ext 比翻译 php 数组快一些,因为它使用缓存,但不利的一点是:MO 中的每个更改都需要重新启动服务器。

I think the best solution would be to extend yii\i18n\GettextMessageSource in your own code library and add the cache ability to GettextMessageSource to enhance its performance and use your extended version as the component.

我认为最好的解决方案是在您自己的代码库中扩展 yii\i18n\GettextMessageSource 并将缓存功能添加到 GettextMessageSource 以提高其性能并使用您的扩展版本作为组件。

protected function loadMessages($category, $language);

Just don't check MO modified date in every load to compare against the cache , instead clear the cache when the MO or PO files are changed (it can be a schedule).

只是不要在每次加载时检查 MO 修改日期以与缓存进行比较,而是在 MO 或 PO 文件更改时清除缓存(它可以是一个时间表)。