문제

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 ...

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.

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 ...

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

Thanks, m.

도움이 되었습니까?

해결책

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

  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.

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.

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

다른 팁

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.

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.

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.

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.

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 ...

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.

The generated files are loaded as normal by 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'.

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.

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.

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.

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/

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.

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.

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).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top