In this post, I will show you my workflow for internationalization of Yii based projects.
We will configure sane paths, logically dividing the frontend and backend. We will also use the yii cli tool to generate the translation files for us. Let’s get started.
- Create messages directory inside the common directory.
- Create a file called i18n.php inside common/config directory.
- Paste the following block of code inside i18n.php.
<?php return [ 'sourcePath' => __DIR__. '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR, 'languages' => ['pt-PT'], //Add languages to the array for the language files to be generated. 'translator' => 'Yii::t', 'sort' => false, 'removeUnused' => false, 'only' => ['*.php'], 'except' => [ '.svn', '.git', '.gitignore', '.gitkeep', '.hgignore', '.hgkeep', '/messages', '/vendor', ], 'format' => 'php', 'messagePath' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'messages', 'overwrite' => true, ];
- Make sure to add all required languages to ‘languages’ array. In the above example I have added Portuguese.
- Add the i18n component to your common/main.php configuration as follows:
'components' => [ ... 'i18n' => [ 'translations' => [ 'frontend*' => [ 'class' => 'yii\i18n\PhpMessageSource', 'basePath' => '@common/messages', ], 'backend*' => [ 'class' => 'yii\i18n\PhpMessageSource', 'basePath' => '@common/messages', ], ], ], ... ],
- You can now:
- Set the language in common configuration i.e. ‘language’ => ‘pt-PT’ inside common/main.php.
- Set the language at runtime i.e. Yii::$app->language = ‘pt-PT’
- See the Yii 2.0 Guide on Internationalization for more details on setting a language.
- In your frontend and backend code, use the following method to create i18n supported strings respectively.
Yii::t('frontend', 'Translatable String');
Yii::t('backend', 'Translatable String');
- Run yii message/extract @common/config/i18n.php to generate the translation files inside common/messages.
- Yii message will generate the translation files as follows:
common/ ... messages/ pt-PT/ backend.php frontend.php ...
- The files frontend.php and backend.php are now ready to edit the Portuguese translations 🙂
There you have it! Once set up correctly, just run step #7 every time you add new translatable strings to your app. Yii CLI tool automatically and safely merges existing translations with the new strings and you can translate the new strings in the generated files.
Further Reading
http://www.yiiframework.com/doc-2.0/guide-tutorial-i18n.html
http://www.yiiframework.com/doc-2.0/yii-baseyii.html#t()-detail
Bonus Tip
You can further organize the translatable files i.e. Yii::t(‘frontend/post’, ‘Translatable String’); will generate common/messages/pt-PT/frontend/post.php with all translatable strings inside.
Hello Coding Ninja,
I was trying out Yii2, I have done this setup before in Yii and I never had this problem.
But if I just straight up follow your guide, and many other implementations, I always get this:
Invalid Call – yii\base\InvalidCallException
Setting read-only property: yii\web\Application::i18n
Stack trace:
#0 *****\\yiisoft\yii2\BaseYii.php(518): yii\base\Compo
nent->__set(‘i18n’, Array)
#1 *****\\yiisoft\yii2\base\Object.php(105): yii\BaseYi
i::configure(Object(yii\console\Application), Array)
#2 *****\yiisoft\yii2\base\Application.php(206): yii\b
ase\Object->__construct(Array)
#3 *****\\yiisoft\yii2\console\Application.php(79): yii
\base\Application->__construct(Array)
#4 *****\\yii(30): yii\console\Application->__construct(Array)
I’m using the Advanced Template.
Hi Andre,
It appears that your error is originating in the common/config/main.php. Check step 4 and make sure that the i18n section is nested inside the components and not outside of it.
See my main.php file below.
You are correct, what a miss. Thank you.
You tell people to add it to the common main file, but the backend isn’t reading AFAIK the configurations from the common main file, which causes it to not load the il8n configuration present in there, and it doesn’t translate
The message file for category ‘app’ does not exist: *****\backend/messages/pt-PT/app.php
Aren’t we suppose to add il8n to the backend and frontend individually? Because they are not accessing the common il8n settings.
Hi Andre,
The backend loads the common config, as seen in backend/web/index.php
I see what’s up, I just don’t understand it.
This works:
'i18n' => [
'translations' => [
'app*' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@common/messages',
]
],
],
This, as I wanted it, doesn’t:
'i18n' => [
'translations' => [
'*' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@common/messages',
]
],
],
Although it is documented here: http://www.yiiframework.com/doc-2.0/guide-tutorial-i18n.html#specifying-default-translation
Hello
No way to paste your php code – do you have an idea why ?
Thanks
Hi,
What browser are you using? You can click on the
<>
icon to get plaintext view of the code.Sorry about this but as I tried many times at last it worked – always with Chrome – I can’t see why it was not working before but now its ok – so thanks for your reply !
Now I applied things on this blog and its working fine 🙂
The translation directory path:
'sourcePath' => __DIR__. '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR,
Is incorrect, it shoud be:
'sourcePath' => __DIR__. DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR,
notice the extra DIRECTORY_SEPARATOR at the start and a single directory level .. removed. With your directory indirection Yii scans also the directories below the main Yii2 installation path.
I have fresh installation of Yii2 advanced with the default directory structure.
Hi Bartosz,
Thanks for the correction. My folder structure might be a little off standard, hence the discrepancy.
I will update the post to reflect the correct path.
Where should i place this Yii::$app->language = ‘pt-PT’ ?
Hello Ninja,
this command doesn’t work with me
yii message/extract @common/config/i18n.php
it gets command not found
This is working in my code.. But class yii\i18n\GettextMessageSource is not loaded the po files. so how to load text from .po files.
I got this error when generate i18n file at step 7:
esoftcard:~/workspace/idoc $ php yii message/extract @common/config/i18n.php
Error: The source path /home/ubuntu/workspace/idoc/common/config../../../ is not a valid directory.
How to fix this please
@esoftcard
in file i18n.php change this line
‘sourcePath’ => __DIR__. ‘..’ . DIRECTORY_SEPARATOR . ‘..’ . DIRECTORY_SEPARATOR . ‘..’ . DIRECTORY_SEPARATOR,
with
‘sourcePath’ => __DIR__. DIRECTORY_SEPARATOR . ‘..’ . DIRECTORY_SEPARATOR . ‘..’ . DIRECTORY_SEPARATOR,
work for me.
Can you help me for Yii1.5 how to use backend and frontend messages?