jquery.i18n icon indicating copy to clipboard operation
jquery.i18n copied to clipboard

How can I translate strings dynamically?

Open TechOverflow opened this issue 2 years ago • 5 comments

I'm having trouble translating strings dynamically. It seems that this is because the translation is loaded after the rest of the code.

main.js (script linked in head)

function _T(key) {
    'use strict';
    var i18n = $.i18n();
    $.i18n().load('../assets/lang/ui_' + $.i18n().locale + '.json', $.i18n().locale).done(function() {
        console.log(key + ' : ' + $.i18n(key));
        return $.i18n(key);
    });
}

page.php

<script type="text/javascript">
    $(document).ready(function () {
        var formats = { portrait : _T('text-portrait'), landscape : _T('text-landscape'), square : _T('text-square') }
        $.each(formats, function (key, format) {
            console.log('appending '+key)
            $('#format').append($('<option>', { 
                value: key,
                text : format
            }))
        })
    })
</script>

console output:

[Log] appending portrait
[Log] appending landscape
[Log] appending square
[Log] text-portrait : Portrait
[Log] text-square : Square
[Log] text-landscape : Landscape

As you can see, the translation happens after the each loop. What is the correct way to preload the translation to ensure it being available when document is ready?

TechOverflow avatar Sep 01 '23 13:09 TechOverflow

Brain fart, the load() needs to be outside of the function. Hope this helps someone else.

var i18n = $.i18n();
$.i18n().load('../assets/lang/ui_' + $.i18n().locale + '.json', $.i18n().locale);

function _T(key) {
    console.log(key + ' : ' + $.i18n(key));
    return $.i18n(key);
}

TechOverflow avatar Sep 01 '23 14:09 TechOverflow

I am still sometimes experiencing that the json file isn't loaded in time for the translations to be done. Is there a way to ensure that the (very small) files are loaded before executing the rest of the script?

TechOverflow avatar Sep 26 '23 12:09 TechOverflow

i think modify the _T function, you can make use of a deferred object (e.g., $.Deferred()) to handle the asynchronous loading of translations :

function _T(key) { 'use strict';

var deferred = $.Deferred(); // Create a deferred object

// Load translations asynchronously
$.i18n().load('../assets/lang/ui_' + $.i18n().locale + '.json', $.i18n().locale).done(function () {
    console.log(key + ' : ' + $.i18n(key));
    deferred.resolve($.i18n(key)); // Resolve the deferred object with the translation
});

return deferred.promise(); // Return the promise from the deferred object

}

Now, the _T function returns a promise. This allows you to use the .done() method when calling _T to handle the asynchronous nature of loading translations:

$(document).ready(function () { // Define the formats without directly calling _T var formats = { portrait: 'text-portrait', landscape: 'text-landscape', square: 'text-square' };

// Load translations asynchronously
var loadOperation = $.i18n().load('../assets/lang/ui_' + $.i18n().locale + '.json', $.i18n().locale);

// Execute after translations are loaded
$.when(loadOperation).done(function () {
    // Populate #format with translated options
    $.each(formats, function (key, translationKey) {
        console.log('appending ' + key);

        // Use _T with .done() to get the translated value
        _T(translationKey).done(function (translatedValue) {
            $('#format').append($('<option>', {
                value: key,
                text: translatedValue
            }));
        });
    });
});

});

Abhinob-Bora avatar Jan 23 '24 12:01 Abhinob-Bora