EzDevInfo.com

i18next

internationalisation (i18n) with javascript the easy way (incl. jquery plugin) i18next - i18n for javascript

HTML tags in i18next translation

I'm using i18next to power i18n for my weblog. It works great on text-only content, but when I try to translate content that includes HTML markup, it is displaying the raw markup when I translate the text.

As an example, here is a snippet of the markup from a post that is not working as expected:

<div class="i18n" data-i18n="content.body">
  In Medellín they have many different types of <i>jugos naturales</i>&nbsp;(fruit juice) ... <br />
  <br />
  ...
</div>

The translation code looks like this:

var resources = {
  "en": ...,
  "es": {
    "translation": {
      "content": {
        "body": "En Medellín hay varios tipos diferentes de <i>jugos naturales</i> ... <br /><br /> ... "
      }
    }
  }
}

i18n.init({"resStore": resources}, function( t ) {
  $('.i18n').i18n();
});

When the translation is rendered, HTML tags are escaped and output as text:

En Medellín hay varios tipos diferentes de &lt;i&gt;jugos naturales&lt;/i&gt;...&lt;br /&gt;&lt;br /&gt;

How do I get i18next to change the HTML of translated elements?


Source: (StackOverflow)

i18next best practice

I've successfully implemented i18next, which by the way is a great library! Though I'm still in search for the "best practice". This is the setup I have right now, which in general I like:

var userLanguage = 'en'; // set at runtime

i18n.init({
    lng                 : userLanguage,
    shortcutFunction    : 'defaultValue',
    fallbackLng         : false,
    load                : 'unspecific',
    resGetPath          : 'locales/__lng__/__ns__.json'
});

In the DOM I do stuff like this:

<span data-i18n="demo.myFirstExample">My first example</span>

And in JS I do stuff like this:

return i18n.t('demo.mySecondExample', 'My second example');

This means I maintain the English translation within the code itself. I do however maintain other languages using separate translation.json files, using i18next-parser:

gulp.task('i18next', function()
{
    gulp.src('app/**')
        .pipe(i18next({
            locales : ['nl','de'],
            output  : '../locales'
        }))
        .pipe(gulp.dest('locales'));
});

It all works great. The only problem is that when I've set 'en' as the userLanguage, i18next insists on fetching the /locales/en/translation.json file, even though it doesn't contain any translations. To prevent a 404, I currently serve an empty json object {} in that file.

Is there a way to prevent loading the empty .json file at all?


Source: (StackOverflow)

Advertisements

Access i18next Translation in Function not in App.js

Im using ExpressJS and i18next.

in app.js

var express = require('express')
  , i18n = require('i18next')
  , user = require('./routes/user')
...
//internationalization
i18n.init({
  lng: 'en-US',
  saveMissing: true,
  debug: true
});
...  
app.use(i18n.handle);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
...
i18n.registerAppHelper(app);
...
app.post('/users/save', user.save);

I can access the translation in jade:

t('app.title')

How can I access the translation in routes.user.js

exports.save = function(req, res){
    //t('app.title')
}

Source: (StackOverflow)

Replacing variables in i18next

I have implemented i18next, and after getting help on a couple of issues all works fine. As a noob i do have some issues understanding part of the documentation on the support site.

I'm trying to replicate this part (found here):

// given resources
{           
  'en-US': { translation: {  key: '__myVar__ are important' } }
};

i18n.t("key", { myVar: "variables" }); // -> variables are important

On my side of things, this is the json file:

{
    "app": {"name": "mytranslation" },

    "back": "Back",
    "cancel": "Cancel",
    "closemenu": "Close Menu",
    "closeoptions": "Close options",
    "currency": "Currency symbol is __currencysymbol__",
    "date": "Date",
    "description": "Description"
}

And the html:

<body>
    <div data-i18n="currency"></div>
    <script src="javascript/i18next-1.7.3.min.js"></script>
    <script language="javascipt" type="text/javascript">
        i18n.init({ preload: ['en', 'fr', 'ht', 'es', 'de', 'zh', 'vi', 'pt', 'it', 'th', 'dev'] });
        i18n.init({ detectLngQS: 'lang' });
        i18n.init(function(t) { 
            $("body").i18n();
            var appName = t("app.name");
        });
        i18n.t("currency", { currencysymbol: "$" }); //where do I place this code???
    </script>
</body>

Note: jQuery 2.1.1 and jQuery Mobile 1.4.2 are loaded in the header.

I'm sure I'm not placing the various parts where they are supposed to go, as it is not working (not inserting the variable "currencysymbol"). The rest of the code works fine, as I get all the translated text.

What I'd really like to achieve is to be able to create variables that would be called as part of the translations (currency symbol, company name, company address, etc... - for affiliates purposes), and be able to replace those values as they are repeated in the translated texts.

I would like to have those variables in one place, so they are easy to adjust, and they will not be subject to the context of language changes.


Source: (StackOverflow)

md-select initialization with i18n

I'm using Angular-material and I18next. Here is my simple example :

<md-select ng-init="val='en'" ng-model="val">
    <md-option ng-value="en">{{'en' | i18next}}</md-option>
    <md-option ng-value="de">{{'de' | i18next}}</md-option>
</md-select>

The select title is initialized with 'en' and not 'English'. But as soon as I select an other value the correct internationnalized value appears as the new select title.

Any idea how to get the select element displaying the internationnalized value from its initialization ?

Thanks, Max

N.B. if I initializes directly with 'English' or any other value different than the values in the options, the select element does not get initialized at all.

Update: It looks like the md-select element title is initialized before the md-option elements inner values are internationnalized. I have no idea how to solve this.


Source: (StackOverflow)

How to wait for Angular module to load?

I'm trying to use i18next (https://github.com/archer96/ng-i18next) in my Angular project, but it seems to be loading too slow. This is my setup:

angular.module('jm.i18next').config(['$i18nextProvider', function ($i18nextProvider) {
    $i18nextProvider.options = {
        lng: 'en',
        fallbackLng: 'en',
        preload: ['en'],
        supportedLngs: ['en'],
        resGetPath: '../locales/__lng__.json',
        useCookie: false,
        useLocalStorage: false,
        defaultLoadingValue: ''
    };
}]);

angular.module('myApp', ['jm.i18next']).controller('MainCtrl', ['$scope', '$i18next', function ($scope, $i18next) {
console.log($i18next("key"));

setTimeout(function() {
    console.log($i18next("key"));
  }, 1000);
}]);

I have to add a timeout to have a value. Is there a way to make sure i18next is ready when the controller is loaded?


UPDATE

I'm trying to group workouts by type, which is translated using $i18next. But this doesnt work, since the view is "ready" before the controller has done the translation.

<select ng-model="workout" ng-options="workout as workout.name group by workout.type for workout in workouts | orderBy: ['type', 'name']"></select>

$scope.workouts = [
    {id: 1, name: 'Workout 1', type: $i18next("type1")},
    {id: 25, name: 'Workout 2', type: $i18next("type2")},
  ];

Source: (StackOverflow)

jQuery Mobile Table Reflow Headers with i18next translations

I want to use the code from this page of the jQuery Mobile Demo site (jQuery Mobile 1.4.2) with the i18next translation tool, however the table headers disappear when viewing the table on mobile.

I understand jQM takes the header tag text and places it in front of the values for each row when the window is smaller than a certain threshold.

I have built a demo here. To view it in action, please change the width of your browser.

The top table has the intended behavior, but inline text for table headers, and the bottom table show the issue, where the i18n table headers appear correctly as One, Two, Three, Four on a wide screen, and they disappear on narrow screen.

I'm looking for a way to use the i18n translations in the headers for mobile view, since it is already implemented across the rest of the site, and works beautifully.

Thanks for your help!


Source: (StackOverflow)

i18next load json error(404 Not Found)

this is my code at index.html

<html>

<head>
    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"/>
    <script src="javascript/jquery-1.11.1.min.js" type="text/javascript"></script>
    <script src="javascript/i18next-1.7.4.js" type="text/javascript"></script>

    <title>i18next test</title>
</head>

<body>
    <p id="id001" data-i18n="first_data">first</p>
</body>

<script type="text/javascript">

$(document).ready(function(){
  language_complete = navigator.language.split("-");
  language = (language_complete[0]);

  i18n.init({
  lng: language, 
  resGetPath: 'locales/__lng__.json',
  fallbackLng: "en",
  }, function(){
    $("first_data").i18n();
  });

});
</script>

</html>

And I've created 2 json file at the same directory with index.html

locales/en.json
locales/de.json

json file content:

{
    "first_data": "de-first-data"
}

Firefox try to load de.json and en.json but get the error 404. enter image description here

Do you have any idea why i18next cannot load the json file.

This is my folder structure below:

index.html
locales/de.json
locales/en.json
javascript/i18next-1.7.4.js
javascript/jquery-1.11.1.min.js

Source: (StackOverflow)

gettext-style keys with i18next, and general workflow

We would like to exchange PO files with translators, and convert these to i18next's native JSON format. This sounds pretty straightforward using the i18next-conv utility.

However, i18next expects more or less special keys; for example the dot has special meaning with regard to i18next namespaces. In contrast, gettext PO files are intended to carry source strings (in the original language) for their message IDs.

We know that message IDs can be arbitrary, and can thus be mapped to i18next keys directly, but we would like to use source strings and use PO files as they were intended for various reasons.

The main reason is that all the translation tools we would like to use, and probably those of all our translators, expect this. Using symbolic keys would make translating a real pain. In any case, we figured from the debates around this that this is mainly a matter of opinion; we kind of made ours, and we would like to put this restriction as a requirement for this question.

  1. Is it really a bad idea to use source strings as i18next keys from a technical standpoint? How hard is it to escape them? Is there anything else than the dot and namespaces that we should care about?
  2. If we determine that we want to keep using symbolic keys, is there an alternative to i18next-conv that can generate i18next JSON translation files from PO files using source strings as message IDs? We understand that we would most likely need to maintain a separate mapping between the symbolic names and the original language strings, and we're prepared to do so.

Moreover, we wonder about the general workflow. How is the original PO file generated? How are the translation files maintained?

  1. If we use source strings as keys in i18next, what are the best tools to extract strings from the codebase? xgettext doesn't seem to support Javascript.
  2. If we use symbolic keys in i18next, how can we best generate the original PO file? Is writing a POT file by hand a good practice?
  3. Again, if we use symbolic keys, how can we easily invalidate translations whenever we update the original language strings? Are there tools for that?

We understand these questions are very basic, but we were a bit surprised at how little information we could find about i18next-gettext integration. The i18next-conv tool exists and works perfectly as advertised, but is it actually useful? Do people actually use it? If so, are our questions relevant?

Finally, are our expectations about the maturity of the system a little too high?


Source: (StackOverflow)

using `i18next.t` from inside my angular controller?

I'm using the library i18ng from https://github.com/mikefrey/i18ng

I need to access the translation function from within a controller though, I can't seem to figure out how this is exposed.

I see the library saves a reference from window.i18n but it doesn't seem to return anything for me.

I've tried this in my controller:

    var t = window.i18n.t;
    $rootScope.pageTitle = t('test'); //should produce "this is a test"

But all I get is an empty string.


Source: (StackOverflow)

npm install i18next-conv: Error: Cannot find module 'readable-stream'

I'm trying to install i18next-conv but, when I run sudo npm install i18next-conv -g, I get this error:

Error: Cannot find module 'readable-stream'
at Function._resolveFilename (module.js:337:11)
at Function._load (module.js:279:25)
at Module.require (module.js:359:17)
at require (module.js:375:17)
at Object.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/sha/index.js:3:48)
at Module._compile (module.js:446:26)
at Object..js (module.js:464:10)
at Module.load (module.js:353:31)
at Function._load (module.js:311:12)
at Module.require (module.js:359:17)

If you need help, you may report this log at:
<http://github.com/isaacs/npm/issues>
or email it to:
<npm-@googlegroups.com>
System Darwin 11.4.2
command "node" "/usr/local/bin/npm" "install" "i18next-conv" "-g"
cwd /Users/personalcomputer/Desktop
node -v v0.6.18
npm -v 1.3.5

Additional logging details can be found in:
    /Users/personalcomputer/Desktop/npm-debug.log
not ok code undefined
not ok code 1

Can anyone tell me what can I do to install it?

Thanks!


Source: (StackOverflow)

i18next not working - i18n not defined

Thanks for reading. I've just got myself extremely confused while trying to add i18next into my first phonegap application. I'm very sure that I'm doing something dumb as I'm a new developer. I'd really like this to be able to work in browser (at least during development) and on device.

At the moment I'm getting the error i18n not defined on the init line

index.html

<!DOCTYPE HTML>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">    
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>Auth Demo 2</title>
    <link rel="stylesheet" rel='nofollow' href="/css/jquery.mobile.min.css" />
    <script type="text/javascript" charset="utf-8" src="cordova-1.8.1.js"></script>
    <script src="js/lib/zepto.min.js"></script>
    <script src="js/lib/i18next.amd.withJQuery.min.js"></script>
    <!-- <script src="js/lib/i18next.min.js"></script> -->
    <script src="js/index.js"></script> 
    <script src="main.js"></script>
</head>
<body>
    <script>
        $(document).ready(function(){
        if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
        document.addEventListener("deviceready", onDeviceReady, false);
        } else {
            onDeviceReady();
        }
        language_complete = navigator.language.split("-");
        language = (language_complete[0]);
        i18n.init({ lng: language }, function() {
            // save to use translation function as resources are fetched
            $("#content-div").i18n();
        });
    }); 
    function onDeviceReady() {
        startupBehavior(); 
    }   
    </script>
    <div id="appPage" data-role="page">
        <div data-role="header">
            <h1>Auth Demo</h1>
        </div>
        <div id="content-div" data-role="content">
            <h2>Auth demo</h2>
        </div>
        <div data-role="footer">
            <h4>Auth demo</h4>
        </div>
    </div>
</body>
</html>

index.js (partial)

function startupBehavior() {
    $("#content-div").children().remove(); //clear the form out
    $("#content-div").append('<form id="auth_login_form">');
    $("#content-div").append('<label for="Email" data-i18n="site.email"></label>');
    $("#content-div").append('<input type="text" id="auth_login_email" value="" data-i18n="site.email" placeholder="Email Address old" />');
    $("#content-div").append('<input type="button" id="auth_login_submit" onClick="handleLogin()">Log me in</input>');
$("#content-div").append('</form>');
}

My only ideas are that i18next doesn't work with zepto or that I might need to use require.js which I've seen mentioned a few times, but wasn't sure if that was only necessary for node.js based stuff, which this is not.


Source: (StackOverflow)

i18next failing to load translation file: "there is a typo"

I've created translation file, validated it at jsonlint, ensured the translation file was located at /locales/translation-en.json.

I consistently get the error,

There is a typo in: locales/translation-en.json

I'm stumped ... here's the translation json I have.

{
   "tab":{
      "legionella":"LEGIONELLA",
      "logbook":"LOGBOOK"
   },
   "representative":{
      "tag":"Representative: __rep__ &#8212; Phone: __phone__ &#8212; ",
      "email":"Click here to email your rep"
   },
   "portlet":{
      "contacts":{
         "title":"Contacts",
         "type":"Contact<br>Type",
         "name":"Contact<br>Name",
         "phone":"Phone<br>Number",
         "type_context_1":"Owner",
         "type_context_2":"Maintenance",
         "type_context_3":"Other"
      },
      "samples":{
         "title":"Legionella Samples",
         "sampleDate":"Sample<br>Date",
         "transmitForm":"Transmittal<br>Form",
         "certOfAnalysis":"Certificate<br>of Analysis",
         "concentration":"Concentration<br>(UFC/L)",
         "correctAction":"Corrective<br>Action",
         "range_context_1":"Interference",
         "range_context_2":"Less than 10,000 UFC/L",
         "range_context_3":"Between 10,000 to 1,000,000 UFC/L",
         "range_context_4":"Greater than 1,000,000 UFC/L"
      },
      "serviceReports":{
         "title":"Service Reports",
         "date":"Report<br>Date"
      },
      "maintenance":{
         "title":"Maintenance Programs",
         "popup":"Create New Maintenance Program",
         "type":"Program<br>Type",
         "date":"Effective<br>Date",
         "document":"Program<br>Document",
         "type_context_1":"Water Treatment",
         "type_context_2":"Mechanical",
         "type_context_3":"Schematic",
         "type_context_4":"O&M Manual",
         "popup_type":"Type",
         "popup_date":"Effective Date",
         "popup_document":"Document",
         "popup_save":"Save Maintenance Program"
      },
      "history":{
         "title":"System History",
         "popup":"Create New System History Entry",
         "date":"Event<br>Date",
         "type":"Event<br>Type",
         "details":"Event<br>Details",
         "type_context_1":"Breakage",
         "type_context_2":"Repair",
         "type_context_3":"Decontamination",
         "type_context_4":"Replacement"
      },
      "reminders":{
         "title":"Reminders",
         "date":"Date",
         "description":"Description"
      },
      "emails":{
         "title":"Emails",
         "date":"Date",
         "subject":"Subject",
         "recipient":"Recipient"
      }
   },
   "common":{
      "view":"View",
      "registryList":"Registry: ",
      "signout":"Sign Out"
   }
}

Source: (StackOverflow)

Attach helpers to Jade when running client side (in browser)

I have made a single page app powered by node js (Express) with a mongo db. I have used jade for templating and have some templates rendered in the browser. The templates render fine except I am unable to workout how to add helpers. In particular i18next.

I have set up a route to template/get/ which looks like this:

var fs = require('fs');
var jade = require('jade');


exports.get = function(req, res){

  fs.readFile('views/partials/listing_snippet.jade', {encoding: 'utf-8'}, function (err, data) {
    if (err) throw err;
    console.log(data);
    t = jade.compile(data, {client: true, compileDebug: false});
    res.send('var template = {listing_snippet: ' + t.toString() + '}');
  });
}

I then include this and jades 'runtime.js' as scripts at the top of my page. The template renders fine by calling template.listing_snippet({locals: foo});

but I can not get i18next's helpers to work. I assume I need to attach the helper somehow... but the documentation is a little thin in that area.


Source: (StackOverflow)

i18next - plural form incorrect

Question, I'm using i18next and all is well, except for plural translations.

Plural translations work great for some languages, but not for others.

For example, Croatian doesn't work. I added some log statements and saw that instead of using the translation key "name_plural" it uses "name_plural_5"..

It has something to do with this piece of code:

        var pluralKey = ns + o.nsseparator + key + o.pluralSuffix;
        var pluralExtension = pluralExtensions.get(lngs[0], options.count);
        if (pluralExtension >= 0) {
            pluralKey = pluralKey + '_' + pluralExtension;
        } else if (pluralExtension === 1) {
            pluralKey = ns + o.nsseparator + key; // singular
        }

Which references this pluralExtension:

            "hr": {
            "name": "Croatian",
            "numbers": [
                1,
                2,
                5
            ],
            "plurals": function(n) {
                return Number(n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
            }
        },

For reference, English looks like this:

        "en": {
            "name": "English",
            "numbers": [
                1,
                2
            ],
            "plurals": function(n) {
                return Number(n != 1);
            }
        },

Now can anyone tell me what this means? Do I need to supply multiple plural translations for this language, and why?

http://i18next.com


Source: (StackOverflow)