Reputation: 4623
Is there any mechanism in yii framework to translate messages in javascript source files.
For example with:
yiic message config-message.php
I can generate translation .php files for all Yii::t().
Is it possible to generate .js files with the same mechanism. Currently I'm including to my javascript json data with table returned by translation file.
Upvotes: 6
Views: 4253
Reputation: 1
Here's my way of doing it.
Little context for my application :
$availableLanguages
variable.$langFiles
that I can change within the controller.use yii\helpers\Json;
use yii\helpers\FileHelper;
$files = FileHelper::findFiles(\Yii::getAlias('@app/messages/'));
$translations = [];
// Loop into all the available languages
foreach($availableLanguages as $lang) {
$translations[$lang] = [];
// Get all the available message files
foreach ($langFiles as $file) {
// Import the php file if it exists
$filePath = \Yii::getAlias("@app/messages/{$lang}/{$file}.php");
$key = "app/{$file}";
$translations[$lang][$key] = file_exists($filePath) ? include($filePath) : [];
// Replace '.' by '_' to use the get method
foreach($translations[$lang][$key] as $msg => $value) {
unset($translations[$lang][$key][$msg]);
$msg = str_replace('.', '_', $msg);
$translations[$lang][$key][$msg] = $value;
}
}
}
?>
<script>
var translations = <?= Json::encode($translations) ?>;
var lang = document.getElementsByTagName('html')[0].getAttribute('lang');
function t(category, message) {
// Get method thats works exactly like lodash
const get = (value, path, defaultValue) => {
return String(path).split('.').reduce((acc, v) => {
try {
acc = acc[v];
if(typeof acc === 'undefined') {
throw "Undefined";
}
} catch (e) {
return defaultValue;
}
return acc;
}, value)
}
// Replace '.' by '_' to use the get method.
var key = message.replace('.', '_');
// If the translation is not found, return the original message
console.log(lang+'.'+category+'.'+key, message);
return get(translations, lang+'.'+category+'.'+key, message);
}
</script>
I can now get the translation directly into my scripts by using the same syntax as in Yii2. Example :
t('app/quotes', 'Hello World. Captain speaking!')
Upvotes: 0
Reputation: 596
I've created an extension that should handle this:
http://www.yiiframework.com/extension/jstrans/
Upvotes: 4
Reputation: 167
I just stumbled over this problem and using a controller to generate js code on the fly is not an option because you will waste resources because of starting an additional PHP process on every request. This may be a problem on high traffic sites. So I implemented a different approach: In the .js messages are stored in Variables e.g.
var MyJsClass = {
lang:
{
foo: 'Foo',
bar: 'Bar',
},
doSomething: function()
{
console.log(this.lang.foo);
},
};
in the view you add the translation if the current language is different to the sourceLanguage of the App:
<?php
$cs = Yii::app()->clientScript;
$cs->registerScriptFile($this->module->assetsUrl.'/js/myjsclass.js');
if (Yii::app()->sourceLanguage != Yii::app()->language) {
$cs->registerScript('MyScriptID', '
MyJsClass.lang.foo = \''.Yii::t('TranslationCategory', 'Translated Foo').'\';
MyJsClass.lang.bar = \''.Yii::t('TranslationCategory', 'Translated Bar').'\';
');
}
?>
Upvotes: 2
Reputation: 41
An alternate solution would be to make Yii include translated messages in the DOM, that will be later accessed by your JS code, so:
Upvotes: 4
Reputation: 31
It's a really problem. Multi languages sites is always problem. YII solve the problem for php code. But js code problem still on place.
I do not very elegant solution but it's works. Create controller/component and generate js code with localization on the fly using t().
/js/get/?file=some-js-file in layout:
Of course, every JS need to be rewrite. If use small pieces of code (cs()->RegisterScript) I use t() as well.
Upvotes: 2
Reputation: 8400
There is no specific way to deal with that issue.
You can for example generate file with an array in with 'message-id' => 'translation' and include the correct one and then do stuff like alert($messages['itemDeleted']) or something.
An alternative could be to make views of your javascript and use the Yii::t() function on it.
Upvotes: 1