How to translate and do the translations the easy way

12 followers

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.

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.

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 regex pattern 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/CMessagesSource.php, line 103:

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.

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.

Total 5 comments

#7503 report it
drsimonz at 2012/03/26 04:54pm
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.

#6191 report it
thefsb at 2011/12/18 10:28am
Null sourceLanguage? '00'?

The article says: "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."

  1. Is there anything in the guide, api docs or source code to suggest that this is the right thing to do?

  2. Why would you want null source language anyway? Yii's translations are always from one language to another.

  3. Doesn't matter what ISO thinks about '00', in Yii it's a string, so you are instructing Yii to look for a translation from '00' to whatever your chosen destination is.

I suggest following The Guide on translations. Otherwise try to understand what you code is really doing from the API spec and source code.

#5243 report it
redguy at 2011/09/26 06:54am
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.

#5236 report it
dckurushin at 2011/09/25 02:40pm
if you reading this article

Check out the language picker... Would be a good addition for this wiki article

http://www.yiiframework.com/extension/languagepicker/

#5230 report it
Say_Ten at 2011/09/24 04:38pm
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

Leave a comment

Please to leave your comment.