- Set Configuration Parameters (Step 1)
- Use Message Labels (Step 2)
- Create Translation Files (Step 3)
- Modify Yii Framework Translations (Optional)
- Modify Yii Framework Code (Optional)
- Create Gii Code Generation Templates (Optional)
Introduction ¶
I wanted to keep all the I18N related translations in separate files, so that I would not need to modify the view files or the model files every time I need to update or fix the translations of application's source language.
So I figured out I can do it this way - it is 100% Yii compatible.
Set Configuration Parameters (Step 1) ¶
First set the value of sourceLanguage
parameter to 2 zeroes.
Numbers are not allowed in ISO language codes, so they make excellent use as null
values.
Then set the value of language
parameter to your default language.
For example, I use en
as default language.
In the file protected/config/main.cfg
:
'sourceLanguage'=>'00',
'language'=>'en',
A good idea is to implement application's language management in a base controller, overriding init()
method.
Language must be set on every controller's execution, or else application's multilingual features do not work as expected.
Another idea is to create and configure a language management behavior for your application.
Use Message Labels (Step 2) ¶
Now you can call and write all Yii::t()
functions with message labels, instead of meaningful text.
For example, I have a model Person
with a last_name
attribute, and I modify attributeLabels()
method.
In the file protected/models/Person.php
:
public function attributeLabels {
return array(
'last_name'=>Yii::t('app','model.person.last_name'),
);
}
Create Translation Files (Step 3) ¶
Now create message file app.php
in all language folders that you are going to use.
For example, I use en
, fr
, de
languages and I need to create the following files:
protected/messages/de/app.php
protected/messages/en/app.php
protected/messages/fr/app.php
And in all of those files you need to write the translated messages labels.
In the file protected/messages/en/app.php
:
'model.person.last_name' => 'Last name',
In the file protected/messages/fr/app.php
:
'model.person.last_name' => 'Nom de famille',
In the file protected/messages/de/app.php
:
'model.person.last_name' => 'Nachname',
Modify Yii Framework Translations (Optional) ¶
Optionally, if you want to modify framework's translations, you can configure application's coreMessages
component to set basePath
to null
. This way the framework searches for translation files in protected/messages
folder.
In the file protected/config/main.php
:
'coreMessages'=>array(
'basePath'=>null,
),
Now you can, for example, copy framework/messages/de/yii.php
and framework/messages/de/zii.php
files to protected/messages/en
, protected/messages/de
and protected/messages/fr
folders, use some regular expression patterns on those files to replace array values with null
s, and they are ready to use.
Now you can modify the following files to suit your needs:
protected/messages/de/yii.php
protected/messages/de/zii.php
protected/messages/en/yii.php
protected/messages/en/zii.php
protected/messages/fr/yii.php
protected/messages/fr/zii.php
Modify Yii Framework Code (Optional) ¶
Optionally, if you want to make use of empty translation strings,
then you can modify translateMessage()
method in CMessageSource
class to comment out empty string check.
NB! Remember this when you upgrade your Yii distribution!
In the file framework/i18n/CMessageSource.php
, line 104
(Yii version 1.1.17):
if(isset($this->_messages[$key][$message]) /*&& $this->_messages[$key][$message]!==''*/)
This is not recommended, unless it is absolutely necessary.
A better way would be to create your own class to handle this case, but since $_messages
is a private property you need to reimplement the translateMessage()
method.
Create Gii Code Generation Templates (Optional) ¶
You can also create your own code generation templates now.
For example, I use Gii module and I use tmpl1
as my code generation template name.
In the file protected/gii/model/templates/tmpl1/model.php
:
public function attributeLabels() {
return array(
<?php foreach($labels as $name=>$label): ?>
<?php echo "'$name'=>Yii::t('app','model.$tableName.$name'),\n"; ?>
<?php endforeach; ?>
);
}
Great Success! ¶
Now you can manage all your translations in one place - under messages
folder.
Re: Modifying the Framework
I wouldn't recommend modifying the framework at all. We did something similar for falling back with translations, i.e. no fr_FR look in fr. Our solution was to create a new message source that extends CPhpMessageSource, overrides the method in question and configured the application to use this new message source.
return array( ... 'components' => array( 'message' => array( 'source' => 'MPhpMessageSource' ) ) );
iirc
modifying any code provided by others
Not only it is not recommended to change framework code (like Say_Ten already posted), but also any code from other providers (i.e. giix templates).
Such modyfication leads to problems with upgrading code when new versions are published. Instead - there is always possibility to configure components to use our own code with our modyfications.
For CPhpMessageSource - you can extend this class and configure 'components' section in config file. For Giix templates you can provide your own templates directory:
'modules'=>array( 'gii'=>array( 'class'=>'system.gii.GiiModule', 'generatorPaths'=>array( 'ext.myGiixTemplates', 'ext.giix-core', ), ), )
and in ext.myGiixTemplates you copy needed templates directory from giix and apply custom modyfications. If you rename the directory (i.e. extensions/myGiixTemplates/crud/templates/[myCrudTemplate]) Giix will allow you to choose template you want to use during code generation of crud.
You do not need to copy generators code, just templates.
Seems like a good compromise
This is great, good idea... it's super annoying having the source language messages in the view files. That makes perfect sense for a simple app, but when you have 10 languages and hundreds of files, not to mention dynamic user-editable messages, it becomes impossible to stay on top of I18N using the normal Yii style. I had to write a very complex tool to make it easier to add and edit translations for all languages. This will save further time once we convert. And it looks like the performance cost of translating for the source language is minuscule.
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.