Localization and how I solved it

Hi everyone!

In my latest project I came across the problem of localization or better said making an app in multiple languages. I want to share the way i solved that with you as i would like to give back at least a little something for what a great tool framework7 is! So let’s get started.

How to detect the users localization?

With this little code snippet i managed todo it:

window.language = (localStorage.getItem('language') || (window.navigator.language || 'en_US')).replace (/-/g, "_");

I am storing the users Language in Local Storage for the case that the user changes the language for the app despite what the device default is.

How to store the different strings:

For that I have created a seperate file to be included in our project:

locales.js

and this is the content of the file:

window.locales = {
    de : {
        language: 'Deutsch',
        
        done: 'Fertig',
        back: 'Zurrück',
        loading: 'lädt....',
        error: 'Fehler',
    },
    en : {
        language: 'English',
        
        done: 'Done',
        back: 'Back',
        loading: 'loading...',
        error: 'Error',
    }
};

This is just an example for English and German Strings.

How to get the string within our app?

window.localize = function (key) {
    var language = window.language
    language = language.replace (/-/g, "_");
    if(!window.locales[language])
        language = language.substring(0,2);
    if(!window.locales[language])
        language = 'en'
   
    return window.locales[language][key] ? window.locales[language][key] : key
}

This function checks for the users language which we stored in window.language before and check’s if the language is supported (stored in our locales.js) if not it falls back to english. Same goes for the key, if that is not present in the given language it falls back to english. Finally if we use an key which is not in our locales.js it will just display the key

A Template7 helper:

T7.registerHelper('localize', function(value,options) {
    return window.localize(value)
})

Usage:

our function can be used now everywhere, in javascript and within our components easy as this:

JavaScript

window.localize('loading')

Template7

{{localize 'back' }}

bother would return

  • in German: lädt…
  • in English: loading…

Making the user set the language

For that I used a simple smartSelect:

        <div class="list">
            <ul>
                <li>
                    <a class="item-link smart-select smart-select-init" data-css-class="views-no-swiping" data-page-back-link-text="{{localize 'back'}}">
                        <select name="language" @change="languageChange">
                            {{#each locales}}
                            <option value="{{@key}}" {{#js_if '@key == window.language'}} selected{{/js_if}}>{{language}}</option>
                            {{/each}}
                        </select>
                        <div class="item-content">
                            <div class="item-inner">
                                <div class="item-title">{{localize 'settingsLanguage'}}</div>
                            </div>
                        </div>
                    </a>
                </li>
            </ul>
        </div>

The method laguageChange looks like that:

        languageChange: function (e) {
            var self = this;
            var app = self.$app;
            localStorage.setItem('language',e.target.value)
            window.language = e.target.value;
            
            self.$update();
            
        },

I hope that this little tutorial was helpful :slight_smile:

6 Likes

How to use placeholders, for example: “Hello, {username}” ? This is a frequent scenario for me

I would do it like that:

{{localize 'userPageHello' }} {{username}}

and in our locales.js would be:

window.locales = {
    de : {
        language: 'Deutsch',
        
        userPageHello: 'Hallo, ',
    },
    en : {
        language: 'English',
        
        userPageHello: 'Hello, '',
    }
};

placeholders within our string would have to be implemented yet.

You don’t understand. Different placeholder position in the line:

en : ‘You have {count} messages’
ru : ‘У вас сообщений: {count}’

That is not implemented yet and would require some changes

Nice!
I would suggest to change these lines in the Get Key function:

language = language.replace (/-/g, "_").substring(0,2);
    if(!window.locales[language])
        language = 'en'

to:

language = language.replace (/-/g, "_");
    if(!window.locales[language])
        language = language.substring(0,2);
    if(!window.locales[language])
        language = 'en'

So when a language has 2 locales implemented, they both will work:

window.locales = {
    nl_BE : {
        language: 'Vlaams',        
        password: 'paswoord',
    },
    nl : {
        language: 'Nederlands',
        password: 'wachtwoord',
    },
1 Like

You could implement the variable in the json like that:

count = getCountnumber();
window.locales = {
    en : {
        language: 'English',
        msgcount: 'You have '+count+' messages',
    },
    ru : {
        language: 'Russian',
        
        msgcount: 'У вас сообщений:'+count,
    }
};
1 Like

Can you put the code on GitHub?