Reputation: 15668
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
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
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.
<script type="text/javascript" src="jquery.localize.js"></script>
to your index html file<h1 data-localize="greeting"> Hello! </h1>
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:
Add language loading and html page updating from 'deviceready'
event callback listener:
$("[data-localize]").localize("system/localization/localization")
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
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:
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
Reputation: 774
Pros:
Cons:
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
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];
And that solves the problem of writing code to get the locale in a different platform such as iOS.
Hope it helps
Upvotes: 2
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
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
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