ChrLipp
ChrLipp

Reputation: 15668

Phonegap/Cordova internationalization support

I am developing a mobile application with Phonegap and I need internationalization - display a html page in different languages. I do understand now that this is not a Phonegap issue - I have to internationalize the web application.

Kind regards, Christian

--- Edit --

Phonegap has a nice Globalization plugin since 2.2.0. It covers a lot of the i18n functionality. Check the docs http://docs.phonegap.com/en/edge/cordova_globalization_globalization.md.html#Globalization

Upvotes: 23

Views: 25606

Answers (9)

Torsten Barthel
Torsten Barthel

Reputation: 3458

I am developing a Cordova-AngularJS Application. I have taken following simple approach. Use a service to do the actual translation:

angular.module('App.services.Localization', [])

.factory('__', ['$window', function(window){
  var lang = navigator.language.split('-')[0];
  console.log('lang: ' + lang);
  //default language
  var default_language = 'de';

  return function(string) {
      var lang_json = window['__' + lang];
      var loc_str = "";
      if(lang_json === undefined){
        //use default lang
        loc_str = window["__" + default_language][string];
      }else{
        loc_str = window["__" + lang][string];
      }

      return loc_str;
  };

}]);

I included a JSON-Object at global Window scope for every language I support in my application. For example:

var __de = {
  'Speisekarte' : 'Speisekarte',
  'Löschen'     : 'Löschen'
}

and

var __en = {
  'Speisekarte' : 'Menu',
  'Löschen'     : 'Delete'
}

You could easily use one JS-File per language to hold the corresponding JSON-Objects.

That way the service could access the objects like

window['__' + lang]

and return the translated string.

All to do now is to inject the Service and its method -getString into every controller that needs localization of static strings. You have also to make a reference to a local scope var to use localization in Template-Files.

Strings that are set inside the controller and strings in Template-Files are translated via

__("stringToBeTranslated");

Here is a controller example:

angular.module('App.controllers.Menu', [
  'App.services.Localization'
])

.controller('MenuController', ['$scope', '__', function(scope, __) {

  //...
  //pass the Localization service __(string)-Method to the local scope to be used in Template-Files
  scope.__ = __;

  //...
}]);

Upvotes: 1

Gaurav Taywade
Gaurav Taywade

Reputation: 8347

Have you tried using ionic framework for same?

Upvotes: 0

medvedNick
medvedNick

Reputation: 4510

If someone like me is wondering, why there is no ready solutions for such a simple task: jQuery.localize can solve your problems.

  1. Add <script type="text/javascript" src="jquery.localize.js"></script> to your index html file
  2. Add tags for localizable html objects: <h1 data-localize="greeting"> Hello! </h1>
  3. Add localization-ru.json to your project:

    { "greeting": "Привет!" }

I've added it to system/localization/localization-ru.json. The ru suffix is the file's language (ru - Russian, for example). You will probably need localization-en.json, localization-de.json etc:

  1. Add language loading and html page updating from 'deviceready' event callback listener:

    $("[data-localize]").localize("system/localization/localization")

  2. For javascript strings localization is as follows:

    $.localize.data.["system/localization/localization"]["greeting"];
    

Where "system/localization/localization" is the path to your localization.json from www folder, and you will probably write a shortcut for it (the first and the last time you actually need to code something).

Upvotes: 2

Fabrizio
Fabrizio

Reputation: 3776

This is my VERY SIMPLE solution. I use jQuery in my APP then add class="lang" to all the elements that contain a string that should be translated, and to the same element I also add:

  • data-lang="variable"
  • data-lang-to="receive" < optional >

for example:

<input type="search" placeholder="Search..." class="lang" data-lang="search" data-lang-to="placeholder" />

this is my class:

var localize={
    locals: {
        'it': {
            click_activation: 'clicca qui per ricevere il codice di attivazione',
            search: "Cerca..."
        },
        'en-us': {
            click_activation: 'click here to re-send the activation code',
            search: "Search User..."
        }
    },
    start: function(lang){
        lang=lang.toLowerCase();
        var langs=this.locals;
        $('.lang').each(function(){
            var txt=$(this).data('lang');
            var to=$(this).data('lang-to');
            if(txt!==''&&typeof langs[lang][txt]!=='undefined'){
                switch(to){
                    case 'text':
                        $(this).text(langs[lang][txt]);
                        break;
                    case 'placeholder':
                    case 'alt':
                    case 'title':
                        $(this).attr(to, langs[lang][txt]);
                        break;
                    case 'html':
                    default:
                        $(this).html(langs[lang][txt]);
                        break;
                }
            }
        });
    }
};

localize.start(lang); //use phonegap globalization to discover this one if you want

Upvotes: 5

John McLear
John McLear

Reputation: 774

I took an approach to this problem that allows others to contribute language translations for my application.

Pros:

  • Uses "web-matured" libraries
  • Crowd Sourced Translations
  • No native hacking
  • Uses templating
  • Very easy to implement HTML/JS and easy to test
  • Supports Language detection
  • Supports Text Direction (BiDi)
  • No Native dependencies at all so will work on Android/iOS/BB/WP yada yada..
  • Testable in web browser

Cons:

  • Your project needs to be open source and fulfill TranslateWiki's requirements
  • Slightly tricky to implement the commit to Gerrit if you come from a branch/merge world.

I used handlebars for templating and the html10n library to provide translation logic, translated strings come from community contributed json files.

TranslateWiki provides the actual translations through the power of crowd-sourcing. Most of the heavy lifting on my implementation is done by TranslateWiki, a free and open source community service from the Wiki Media Foundation.

Handlebars and the html10n library are powerful, built for the web and widely used. They prove to be extremely useful libraries for this implementation.

No native code or plugins are required.

index.html

<head>
  <script type="text/javascript" src="js/handlebars.js"></script>
  <script type="text/javascript" src="js/html10n.js"></script>
  <link rel="localizations" type="application/l10n+json" href="locales.json">
</head>
<body>
    {{html10n "helloWorld"}}
</body>

locales.json

{
  "fr":"locales/fr.json",
  "en":"locales/en.json"
}

locales/en.json

{
  "en":{
    "helloWorld":"Hello Cruel World"
  }
}

locales/fr.json

{
  "fr":{
    "helloWorld":"Hello Baguette World"
  }
}

index.js

Handlebars.registerHelper('html10n', function(str,a){
  return (html10n != undefined ? html10n.get(str) : str);
});

To switch between languages bring up your browser javascript console and type

html10n.localize("fr");

Some additional logic is needed to do browser language detection, I use Etherpad's implementation to accomplish this.

var language = document.cookie.match(/language=((\w{2,3})(-\w+)?)/);
if(language) language = language[1];
html10n.bind('indexed', function() {
  html10n.localize([language, navigator.language, navigator.userLanguage, 'en'])
})
html10n.bind('localized', function() {
  document.documentElement.lang = html10n.getLanguage()
  document.documentElement.dir = html10n.getDirection()
  // Then I display the index page using handlebars to render a template.
});

That's it, a hack free recipe for rolling out i18n in your Cordova Application.

Upvotes: 11

nicoabie
nicoabie

Reputation: 2894

I've taken a different approach based on @ChrLipp

super.loadUrl("file:///android_asset/www/index.html?lang=" + lang);

then I have a js script that load the correct files depending on the language provided in the query string

(function() {
    var lang;
    try {
        lang = RegExp('[?&]lang=([^&]*)').exec(window.location.search)[1];
    } catch (ex) {
        lang = "es";
    }
    document
            .write(unescape("%3Cscript type='text/javascript' src='locale/angular-locale_"
                    + lang + ".js'%3E%3C/script%3E"));
    document
            .write(unescape("%3Cscript type='text/javascript' src='locale/i18n_"
                    + lang + ".js'%3E%3C/script%3E"));
})();

Using this approach it scales easily.

After writing this answer I found out a better way, just using js:

lang = navigator.language.split('-')[0];

Mozilla developer, navigator

And that solves the problem of writing code to get the locale in a different platform such as iOS.

Hope it helps

Upvotes: 2

ZeoS
ZeoS

Reputation: 72

I couldn't find any framework for doing this so I started my own plugin. I wanted to write only one html and let the internationalization happen with strings.xml (I'm only interested in android right now).

Take a look at it, it might help you: https://github.com/zeitos/i18nplugin

Upvotes: 1

ChrLipp
ChrLipp

Reputation: 15668

I did exactly what Bourbon suggested, because it is a small app and duplication was not that issue. However there are templating frameworks, I think mostly used is mustache.

I solved the selection of the language like this:

@Override
public void onCreate(final Bundle savedInstanceState)
{
    // ...
    String language = getValue("language", "de");
    if (language.equals("de")) {
        super.loadUrl("file:///android_asset/www/de/index.html", 1);
    }
    else {
        super.loadUrl("file:///android_asset/www/en/index.html", 1);
    }
}

private String getValue(final String key, final String defaultValue)
{
    SharedPreferences prefs = getSharedPreferences(
            getApplicationInfo().packageName, MODE_PRIVATE);
    return prefs.getString(key, defaultValue);
}

As you can see, I read the value fro the SharedPreferences. I also created a Phonegap plugin to set this value from the JavaScript code whenever the user changes the language.

Upvotes: 7

Bourbon
Bourbon

Reputation: 1065

Phonegap is just a framework to be able to show web pages in an native-app, and using some plugin to connect with device's hardware sensors. The support of internationalization will depend on your html/js design.

For exemple you can use :

/html/en/index.html
/html/fr/index.html
...

And call the good page depending on the user's language.

Hope this will help you :-)

Upvotes: 9

Related Questions