#### Translation - Fallback Language

Statistics Invoices Schedule

##### 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, tooltips, badges etc:

Example markup:

    <!-- Dropdown menu -->
    <div class="dropdown-menu">
    	<a href="?lng=en" class="dropdown-item english">
    		<img src="assets/images/flags/gb.png" class="img-flag" alt="">
    		English
    	</a>

    	<a href="?lng=ru" class="dropdown-item spanish">
    		<img src="assets/images/flags/es.png" class="img-flag" alt="">
    		Spanish
    	</a>

    	<a href="?lng=ua" class="dropdown-item italian">
    		<img src="assets/images/flags/it.png" class="img-flag" alt="">
    		Italian
    	</a>
    </div>
    <!-- /dropdown menu -->

JS code example:

    // Set init options
    i18next
    .use(i18nextXHRBackend)
    .use(i18nextBrowserLanguageDetector)
    .init({
        backend: {
            loadPath: '../../../../global_assets/locales/{{lng}}.json'
        },
        fallbackLng: 'en'
    },
    function (err, t) {

        // Initialize library
        jqueryI18next.init(i18next, $);

        // Initialize translation
        $localizationElement.localize();
    });

##### 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 russian, 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]/jquery.min.js"></script>
    		<script src="[PATH]/i18next.min.js"></script>
    		<script src="[PATH]/jquery-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:

    // Initialize i18next
    i18next.init({
        // Options
    },
    function (err, t) {
        // Initialize
    });

    // Change language on button click
    $(englishLangClass).on('click', function () {

        // Change language
        i18next.changeLanguage('en');

        // When changed, run translation again
        i18next.on('languageChanged', function() {
            $localizationElement.localize();
        });
    });

###### 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:

    // Initialize
    i18next
    .use(i18nextXHRBackend)
    .use(i18nextBrowserLanguageDetector)
    .init({
    	lng: 'en',
        backend: {
            loadPath: '../../../../global_assets/locales/{{lng}}.json'
        },
        debug: true,
        fallbackLng: false
    },
    function (err, t) {

        // Initialize library
        jqueryI18next.init(i18next, $);

        // Initialize translation
        $localizationElement.localize();
    });

After init example:

    // Initialize
    i18next
    .use(i18nextXHRBackend)
    .use(i18nextBrowserLanguageDetector)
    .init({
        debug: true
    },
    function (err, t) {

        // Initialize library
        jqueryI18next.init(i18next, $);

        // Initialize translation
        $localizationElement.localize();
    });

    // Extend existing translations
    i18next.addResourceBundle('en', 'translations', {
    	key: 'value',
    }, true, true);

##### Library options

The default export of the i18next module is an i18next instance ready to be initialized by calling `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
whitelist | `false` | array of allowed languages
nonExplicitWhitelist | `false` | if true will pass eg. `en-US` if finding `en` in whitelist
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`
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
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
Translation defaults
simplifyPluralSuffix | `true` | will use 'plural' as suffix for languages only having 1 plural form, setting it to false will suffix all with numbers
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
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
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`