23

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

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

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

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

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

Yii 是否有任何推荐的范式有一些解决方案?

谢谢,米。

4

4 回答 4

19

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

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

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

数据库与此类似:

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

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

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

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

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

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

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

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

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

于 2010-11-08T21:22:49.910 回答
17

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

  1. CPhpMessageSource:翻译作为键值对存储在 PHP 数组中。
  2. CGettextMessageSource:翻译存储为 GNU Gettext 文件。(采购订单文件)
  3. CDbMessageSource:消息翻译存储在数据库表中。

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

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

于 2010-03-25T17:13:50.710 回答
1

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

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

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

于 2010-06-15T03:27:25.200 回答
0

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

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

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

protected function loadMessages($category, $language);

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

于 2016-09-05T08:37:51.223 回答