Translation features

accessing resources

with default namespace
// given resourcefile translation.en.json
{
  key1
: 'value of key 1'
}
 
i18n
.t("key1"); // -> value of key 1
with namespaces set
// given resourcesfile namespace1.en.json (default ns)
{
   key1
: 'value of key 1'
}
 
// given additional resourcesfile namespace2.en.json
{
  keys
: {
   
2: 'value of key 2',
   
3: 'value of key 3'
 
}
}
 
i18n
.t("key1"); // -> value of key 1
i18n
.t("namespace1.key1"); // -> value of key 1
i18n
.t("keys.2"); // -> missing key
i18n
.t("namespace2:keys.2"); // -> value of key 2
i18n
.t("namespace2:keys.3"); // -> value of key 3
using multiple keys (first found will be translated)
// given resourcefile translation.en.json
{
  key1
: 'value of key 1'
}
 
i18n
.t(["notExists", "key1"]); // -> value of key 1

why this might be useful for you too: see discussion

Hint: You can change namespace and/or key separator by setting options on init:

  • nsseparator = ':::'
  • keyseparator = '::'
  • i18n.t("namespace2:::keys::2"); // -> value of key 2

multiline in json

// given resources in arabic
{          
 
'en-US': {
    translation
: {  
      key
: [
       
"line1",
       
"line2",
       
"line3"
     
]
   
}
 
}
};

The translation will be joined with '\n'.

Hint: This might be useful in combination with post processing.

providing a default value

// given resources
{          
 
'en-US': { translation: { // key not found } }
};
 
i18n
.t("key", { defaultValue: "my text" }); // -> my text
 
// or shorter given i18next.init({ shorcutFunction: 'defaultValue' });
i18n
.t("key", "my defalut value");

If a resource key isn't resolvable (en-US -> en -> fallbackLng) than normally the key would be returned as string value. You can provide a better default by passing in option defaultValue.

The default value will be send in sendMissing resources, too.

nested resources

// given resources
{
  dev
: { translation: { nesting1: '1 $t(nesting2)' } },
  en
: { translation: { nesting2: '2 $t(nesting3)' } },            
 
'en-US': { translation: {  nesting3: '3' } }
};
 
i18n
.t("nesting1"); // -> 1 2 3

Will return '1 2 3'.

All other options like plurals, ... will work as expected

Hint: You can change pre-/suffix by setting options on init:

  • reusePrefix = '$t(',
  • reuseSuffix = ')',

nested resources with option replace

// given resources
{
  dev
: { translation: { girlsAndBoys_plural: '$t(girls, {"count": __girls__}) and __count__ boys' } },
  en
: { translation: { girls_plural: '__count__ girls' } }
};
 
i18n
.t("nesting1", {count: 2, girls: 3}); // -> 3 girls and 2 boys

You could change interpolationPrefix/Suffix (default '__') on need.

replacing variables

// given resources
{          
 
'en-US': { translation: {  key: '__myVar__ are important' } }
};
 
i18n
.t("key", { myVar: "variables" }); // -> variables are important

Will return 'variables are important'.

You can even have hierarchical variables in form __some.child__.

Hint 1: You can change pre-/suffix by setting options on init or on calling t function with options:

  • interpolationPrefix = '__',
  • interpolationSuffix = '__',

Hint 2: You could even have nested values like:

// given resources
{          
 
'en-US': { translation: {  key: '__person.name.first__ is important' } }
};
 
i18n
.t("key", { person: { name: { first: 'cristina' } } }); // -> cristina is important

Hint 3: Enscaping:

// given resources
{           
  'en-US': { 
    translation: { 
      key1: Not escaped __nameHTML__,
      key2: Escaped __name__ 
    } 
  }
};
 
i18n.t("key2", { name: '', escapeInterpolation: true }); // -> Escaped <tag>
i18n.t("key1", { name: '', escapeInterpolation: true }); // -> Not escaped <tag>

Adding suffix 'HTML__' to your value will prevent the escaping even if option is set so.

You could turn on escaping on init i18n.init({escapeInterpolation: true}); or by passing in option to t function like in the sample.

Formating:

numbers or currency: You might try numeraljs.

dates or time: You might try momentjs.

sprintf support

// given resources
{          
 
'en-US': { translation: {  
    key1
: 'The first 4 letters of the english alphabet are: %s, %s, %s and %s',
    key2
: 'Hello %(users[0].name)s, %(users[1].name)s and %(users[2].name)s'
 
}}
};
 
i18n
.t("key1", { postProcess: 'sprintf', sprintf: ['a', 'b', 'c', 'd'] });
i18n
.t("key2", { postProcess: 'sprintf', sprintf: { users: [{name: 'Dolly'}, {name: 'Molly'}, {name: 'Polly'}] } } );
|
 
// or simpler given i18next.init({ shorcutFunction: 'sprintf' });
i18n
.t("key1", 'a', 'b', 'c', 'd');

For more information about sprintf and source go to dive.into.javascript.

Hint: You can set i18next to always postProcess with sprintf by init with option postProcess: i18n.init({ postProcess: 'sprintf' });

simple plural

// given resources
{          
 
'en-US': {
    translation
: {  
      key
: '__count__  child',
      key_plural
: '__count__  children'
   
}
 
}
};
 
i18n
.t("key", { count: 0 }); // -> 0 children
i18n
.t("key", { count: 1 }); // -> 1 child
i18n
.t("key", { count: 5 }); // -> 5 children

The variable __count__ is optional.

multiple plural forms

// given resources in arabic
{          
 
'ar': {
    translation
: {  
      key
: 'singular',
      key_plural_0
: 'zero',
      key_plural_2
: 'two',
      key_plural_3
: 'few',
      key_plural_11
: 'many',
      key_plural_100
: 'plural'
   
}
 
}
};
 
i18n
.t("key", { count:   0 }); // -> zero
i18n
.t("key", { count:   1 }); // -> singular
i18n
.t("key", { count:   2 }); // -> two
i18n
.t("key", { count:   3 }); // -> few
i18n
.t("key", { count:   4 }); // -> few
i18n
.t("key", { count: 104 }); // -> few
i18n
.t("key", { count:  11 }); // -> many
i18n
.t("key", { count:  99 }); // -> many
i18n
.t("key", { count: 199 }); // -> many
i18n
.t("key", { count: 100 }); // -> plural

What did you expect ;).

Hint: i18next provides the functionality for all languages.

You can override the existing rules via 'i18n.pluralExtension.addRule(lng, obj)'

// sample for arabic
i18n.pluralExtension.addRule("ar", {
  "name": "Arabic", 
  "numbers": [ 0, 1, 2, 3, 11, 100 ],
  "plurals": function(n) { return Number(n === 0 ? 0 : n == 1 ? 1 : n == 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5); }
});

Definitions can be found here.

use translation contexts

// given resources
{          
 
'en-US': {
    translation
: {  
     
friend: 'A friend',
      friend_male
: 'A boyfriend',
      friend_female
: 'A girlfriend'
   
}
 
}
};
 
i18n
.t("friend", { count: 0 }); // -> A friend
i18n
.t("friend", { context: 'male' }); // -> A boyfriend
i18n
.t("friend", { context: 'female' }); // -> A girlfriend

This feature can be combined with plurals.

eg. key: friend_male_plural: '__count__ boyfriends'

return an objectTree

This might be helpful if you need resources for a plugin or library like moment.js.

// given resources
{          
 
'en-US': {
    translation
: {  
      tree
: { res: 'added' }
 
}
};
 
i18n
.t("tree", { returnObjectTrees: true }); // -> { res: 'added' }

Hint: All other features (variables, plurals,...) will be applied befor returning tree.

You can turn on this globally by setting the option in i18n.init({ returnObjectTrees: true }).

manually handle objectTree

This might be helpful if you need resources depending on some app state.

// given resources
{          
 
'en-US': {
    translation
: {  
      state
: { on: 'online', off: 'offline' }
 
}
};
 
 
i18n
.init({objectTreeKeyHandler: function(key, value, lng, ns, options)
 
return (app.online) ? i18n.t(key + '.on') : i18n.t(key + '.off')
})
 
i18n
.t("state", { returnObjectTrees: false }); // -> if app.online online else offline

i18n.init({ objectTreeKeyHandler: function(key, value, lng, ns, options) {...} ).

access value in different language

i18n.t("my.key", { lng: "de-DE" }); // -> will get value in de-DE instead of en-US

You should preload the additional languages on init!

Hint: If the additional language wasn't preloaded it will be fetched synchronous.

check if a key exists

i18n.exists("my.key", options); // same options as in t function

post processing translations

Adding a post processor

eg. add a post processor parsing markdown.

i18n.addPostProcessor("myProcessorsName", function(value, key, options) {
 
return 'some post processed data based on translated value';
});

Using a post processor on translation

i18n.t("my.key", { postProcess: "myProcessorsName" }); 

i18next will translate the key as usual. Then it passes the translation text to the post processor.

Hint: Alternatively you can set i18next to always postProcess with a specific postProcessor by init with option postProcess: i18n.init({ postProcess: 'myProcessorsName' });

send missing resources to server

Turn it on:

i18n.init({ sendMissing: true });

All keys unable to resolve will be send to: 'locales/add/dev/translation'

Additional Options:

var options = { 
 
// change path
  resPostPath
: 'locales/add/__lng__/__ns__',
 
 
// change sendType
  sendType
: 'POST|GET', // default: POST
 
 
// send missing values to
  sendMissingTo
: 'fallback|current|all',
 
 
// change async / sync
  postAsync
: true|false // default: true
}
 
i18n
.init(options);

You can send missing values to the fallbackLng, the current language or all languages (eg. 'en-US', 'en', 'fallback')