Fallback language
Example of defined fallback
language. If user selects any
language that is missed or detected user navigator language doesn't exist in your
/locales/
folder, defined fallback language will be loaded. In this example
Spanish and Italian language files don't exist in /locales/
folder. When
one of these languages is selected, English language specified in
fallbackLng
option will be loaded.
Change language directly:
Simple inline text:
Including attributes, links, badges etc:
Example markup:
<!-- Dropdown menu -->
<div class="dropdown-menu">
<a href="?lng=en" class="dropdown-item en">
<img src="[path to flag]/gb.svg" height="22" alt="">
<span class="ms-2">English</span>
</a>
<a href="?lng=ua" class="dropdown-item es">
<img src="[path to flag]/es.svg" height="22" alt="">
<span class="ms-2">Spanish</span>
</a>
<a href="?lng=it" class="dropdown-item it">
<img src="[path to flag]/it.svg" height="22" alt="">
<span class="ms-2">Italian</span>
</a>
</div>
<!-- /dropdown menu -->
JS code example:
// Define elements
const selector = document.querySelectorAll('[data-i18n]');
// Set init options
i18next
.use(i18nextXHRBackend)
.use(i18nextBrowserLanguageDetector)
.init({
backend: {
loadPath: 'assets/demo/locales/{{lng}}.json'
},
fallbackLng: 'en'
},
function (err, t) {
selector.forEach(function(item) {
item.innerHTML = i18next.t(item.getAttribute("data-i18n"));
});
});
i18next library
Overview
Internationalization
and localization
are means of
adapting web applications to different languages, regional differences and technical
requirements of a target market. Internationalization
is the process of
designing an application so that it can potentially be adapted to various languages and
regions. Localization
is the process of adapting internationalized
application for a specific region or language by adding locale-specific components and
translating text. Framework template uses i18next
library for
internationalization and localization.
Main i18next benefits:
- Support of variables
- Support of nesting
- Support of context
- Support of multiple plural forms
- Gettext support
- Sprintf support
- Detect language
- Graceful translation lookup
- Custom post processing
- Post missing resources to server
- Resource caching in browser
- Fetch resources from server
Basic usage
i18next is a full-featured i18n javascript library for translating your web application. By default, Limitless template supports language switching in 2 different ways: language detection according to the user navigator language and fallback languages. All plugin settings also support and use cookies/localStorage by default. For demonstration purposes, sidebar nav examples are translated to ukrainian and default english languages. You can change current language by choosing it in the dropdown menu located in top navbar.
Page markup:
<!DOCTYPE html>
<html>
<head>
<script src="[PATH]/i18next.min.js"></script>
<script src="[PATH]/i18nextXHRBackend.min.js"></script>
<script src="[PATH]/i18nextBrowserLanguageDetector.min.js"></script>
</head>
<body>
<ul class="navigation">
<li><a href="#" data-i18n="nav.dash.main"></a></li>
<li><a href="#" data-i18n="nav.email.main"></a></li>
<li><a href="#" data-i18n="nav.snippets.main"></a></li>
</ul>
</body>
</html>
Loaded resource file (assets/locales/*.json):
{
"app": {
"name": "Limitless template"
},
"nav": {
"home": "Home page",
"dash": {
"main": "Dashboards",
"templates": "Layout templates"
},
"email": {
"main": "Email templates",
"versions": "Versions"
},
"snippets": {
"main": "Snippets"
}
}
}
Javascript code:
// Define main elements
const elements = document.querySelectorAll('.language-switch .dropdown-item');
// Initialize i18next
i18next.init({
// Options
},
function (err, t) {
// Initialize
});
// Change language on button click
elements.forEach(function(toggler) {
toggler.addEventListener('click', function(e) {
// Here goes navigation menu config
});
});
Set language on init and after init
The plugin allows you to set specified language on init
and
after init
. If language is set on init, resources will be resolved in this
order: 1) try languageCode plus countryCode, eg. 'en-US'
; 2) alternative
look it up in languageCode only, eg. 'en'
;
3) finally look it up in definded fallback language, default: 'dev'
. If
language is not set explicitly, i18next tries to detect the user language by: 1)
querystring parameter ?lng=en
; 2) localStorage; 3) cookie; 4) language set
in navigator.
On init example:
// Elements
const selector = document.querySelectorAll('[data-i18n]');
// Initialize
i18next
.use(i18nextXHRBackend)
.use(i18nextBrowserLanguageDetector)
.init({
lng: 'en',
backend: {
loadPath: 'assets/demo/locales/{{lng}}.json'
},
debug: true,
fallbackLng: false
},
function (err, t) {
selector.forEach(function(item) {
item.innerHTML = i18next.t(item.getAttribute("data-i18n"));
});
});
After init example:
// Elements
const selector = document.querySelectorAll('[data-i18n]');
// Initialize
i18next
.use(i18nextXHRBackend)
.use(i18nextBrowserLanguageDetector)
.init({
debug: true
},
function (err, t) {
selector.forEach(function(item) {
item.innerHTML = i18next.t(item.getAttribute("data-i18n"));
});
});
// Extend existing translations
i18next.addResourceBundle('en', 'translations', {
key: 'value'
}, true, true);
Library options
init
. You can create additional instances using the
createInstance
function. The library supports 30+ default options applicable
for the default usage only, as well as various options for all integrations and
plugins/extensions. Table below demonstrates the list of default i18Next options with
default values and descriptions.
Option | Default | Description |
---|---|---|
Logging | ||
debug | false |
logs info level to console output. Helps finding issues with loading not working. |
Languages, namespaces, resources | ||
resources | undefined |
resources to initialize with (if not using loading or not appending using addResourceBundle) |
lng | undefined |
language to use (overrides language detection) |
fallbackLng | 'dev' |
language to use if translations in user language are not available |
supportedLngs | false |
array of allowed languages |
nonExplicitSupportedLngs | false |
if true, will consider variants as supported when the main language is. E.g.
en-US will be valid if en is in
supportedLngs |
load | 'all' |
language codes to lookup, given set language is 'en-US':
'all' --> ['en-US', 'en', 'dev'] ,
'currentOnly' --> 'en-US' ,
'languageOnly' --> 'en' |
preload | false |
array of languages to preload. Important on serverside to assert translations are loaded before rendering views. |
lowerCaseLng | false |
language will be lowercased eg. en-US --> en-us
|
cleanCode | false |
main language will be lowercased; e.g. EN ⇒ en ,
while leaving full locales like en-US |
ns | 'translation' |
string or array of namespaces to load |
defaultNS | 'translation' |
default namespace used if not passed to translation function |
fallbackNS | false |
string or array of namespaces to lookup key if not found in given namespace |
partialBundledLanguages | false |
allows some resources to be set on initialization while others can be loaded using a backend connector |
Missing keys | ||
saveMissing | false |
calls save missing key function on backend if key not found |
updateMissing | false |
experimental: enable to update default values using the saveMissing (Works only if defaultValue different from translated value. Only useful on initial development or when keeping code as source of truth not changing values outside of code. Only supported if backend supports it already) |
saveMissingTo | 'fallback' |
'current' or 'all' |
saveMissingPlurals | true |
will save all plural forms instead of only singular if t was called for plurals |
missingKeyHandler | false |
function(lng, ns, key, fallbackValue) { } used for custom
missing key handling (needs saveMissing set to true!) |
parseMissingKeyHandler | noop |
function(key) { // return value to display } |
appendNamespaceToMissingKey | false |
appends namespace to missing key |
missingInterpolationHandler | noop |
function(text, value) { return 'stringWithAlternativeValueOrUndefined' }
gets called in case a interpolation value is undefined. This method will not
be called if the value is an empty string or null |
missingKeyNoValueFallbackToKey | false |
used to not fallback to the key as default value, when using saveMissing functionality. * i.e. when using with i18next-http-backend this will result in having a key with an empty string value |
Translation defaults | ||
postProcess | false |
string or array of postProcessors to apply per default |
returnNull | true |
allows null values as valid translation |
returnEmptyString | true |
allows empty string as valid translation |
returnObjects | false |
allows objects as valid translation result |
returnDetails | false |
returns an object that includes information about the used language, namespace, key and value |
returnedObjectHandler | noop |
function(key, value, options) {} gets called if object was
passed in as key but returnObjects was set to false |
joinArrays | false |
char, eg. '\n' that arrays will be joined by |
overloadTranslationOptionHandler | function(args) { return { defaultValue: args[1] }; }; |
default: sets defaultValue |
interpolation | {...} |
see interpolation |
skipInterpolation | false |
allow translate function to skip interpolation and return raw values instead |
Plugin options | ||
detection | undefined |
options for language detection - check documentation of plugin |
backend | undefined |
options for backend - check documentation of plugin |
cache | undefined |
options for cache layer - check documentation of plugin |
Misc | ||
initImmediate | true |
triggers resource loading in init function inside a setTimeout (default async behaviour). Set it to false if your backend loads resources sync - that way calling i18next.t after init is possible without relaying on the init callback. |
keySeparator | '.' |
char to separate keys |
nsSeparator | ':' |
char to split namespace from key |
pluralSeparator | '_' |
char to split plural from key |
contextSeparator | '_' |
char to split context from key |
appendNamespaceToCIMode | false |
prefixes the namespace to the returned key when using cimode
|
ignoreJSONStructure | true |
if a key is not found as nested key, it will try to lookup as flat key |
maxParallelReads | 10 |
limits parallel reads to the backend to prevent opening up to thousands of sockets or file descriptors at the same time |