liysd
liysd

Reputation: 4623

How to deal with javascript internationalization

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

Answers (6)

Here's my way of doing it.

Little context for my application :

  • Available languages differ from one section to another, and is available through the $availableLanguages variable.
  • I have created very small message files to be able to make public some of them without any security issue. I then created a variable called $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

Henk
Henk

Reputation: 596

I've created an extension that should handle this:

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

Upvotes: 4

mirsch
mirsch

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

ereslibre
ereslibre

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:

  1. You do not need to repeat JS code.
  2. Translation is centralized in the PHP/Yii framework.

Upvotes: 4

Andrejs Pankins
Andrejs Pankins

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

Blizz
Blizz

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

Related Questions