This code is heavily inspired by, and borrows from, Mozilla's i18n-abide project.
However, this code has been stripped down to support only those things needed by the Webmaker tools and apps, and is based on
JSON instead of PO files, uses a different form of client-side localization, etc.

The middleware function is used with Express. It should be placed early on in the order of your middleware
functions, such that it can detect and process any extra language (i.e., language codes on the URL or
accept-language header. You use it like so:

var i18n =require('webmaker-i18n');

...

app.use(i18n.middleware({

supported_languages:[

'en-US','th-TH','ru'

],

default_lang:'en-US',

translation_directory: path.join(__dirname,'locale')

}));

This will cause the app to look for three locales on startup:

locale/en_US

locale/th_TH

locale/ru

You can change the root locale directory by passing translation_directory with another path to the
middleware function. Notice how the language tags have been converted
to locale names (i.e., en-US becomes en_US). Each locale directory must have one file named messages.json
which contains the strings for the locale.

When middleware is used, all subsequent middleware and routes will have req and res objects
with additional features. These include:

Often one wants to map locale-specific languages to a default. For example, if there are 3 locales specified
for English: en-US, en-GB, en-CA. If a user requests en, we might choose to use en-US as the
default. Doing such mappings is accomplished using the mappings option:

var i18n =require('webmaker-i18n');

...

app.use(i18n.middleware({

supported_languages:[

'en-US','en-GB','en-CA','th-TH','ru-RU'

],

default_lang:'en-US',

warnings:true,

translation_directory: path.join(__dirname,'locale'),

mappings:{

'en':'en-US',

'th':'th-TH',

'ru':'ru-RU'

}

}));

Here 8 languages are identified, 5 locale-based, and 3 defaults with no locale. Using such mappings,
users can request th or th-TH and get the same result. NOTE: no mappings are applied by default.

warnings option is set to false by default. This option will enable language mapping console debug to see if the language that you are mapped to is successfully configured.

name: The name of your project on Transifex which can be found in the url slug

https://www.transifex.com/projects/p/webmaker/

category_name: The category of your resource file(s) that you want to download for your project

Webmaker.org has weblitstandard.json and webmaker.org.json which are both categorized under webmaker.

Now all the languages in your Transifex project will be downloaded to "path_to_save_files", for example your locale directory. Each language will be stored as a locale-Country pair (i.e., en_US).

var i18n =require('webmaker-i18n');

app.use( i18n.middleware({

supported_languages:['*'],

default_lang:'en-US',

translation_directory: path.join(__dirname,'locale'),

mappings:{

'en':'en-CA'

}

}));

Note: If you set ['*'] to the supported_languages option, the language codes will be read from the specified translation directory and supported_languages will be updated with the new list. This assumes you have already downloaded or otherwise created these directories yourself. For example, if you have locale/en_US and locale/fr the list of supported languages will include en-US and fr.

The localeInfo object contains all the locale information listed below:

If the request comes in as "en-CA"

localeInfo.name = "English (Canada)"

localeInfo.engName = "English (Canada)"

localeInfo.lang = "en-CA"

localeInfo.locale = "en_CA"

localeInfo.momentLang = "en-ca"

localeInfo.direction = "ltr"

localeInfo.langPrefs = "[ 'en', 'es' ]"

localeInfo.alternateLangs = "['en']"

Note:

localeInfo.langPrefs is returned by req.headers['accept-language']. We parse only the next preferred language from the list exluding first element in array.

localeInfo.alternateLangs is a list of matched supported language compared to localeInfo.langPrefs. In other words, alternateLangs is a list of other locales/langs that were specified in accept-langauge and are also supported in the current instance..

The localized.js script is usable with require.js or other AMD module loaders, and also in vanilla JavaScript.
In both cases, the code assumes that the HTML page it lives in has language information stored in the HTML element:

In some cases, it might be desirable to have the localized object placed on the global (e.g., window) even though requirejs is present in the page. This can be accomplished by assigning true to window.__LOCALIZED_IGNORE_REQUIREJS.

ready - a function that initializes the strings (i.e., downloads) on the client-side. A callback
should be passed, as well as any desired options, which include noCache (whether to do cache busting, default is no)
and url (the url end-point to use to call getStrings -- see above, default is '/strings/'). If the url
is an absolute URL beginning in "http", the URL will not be processed in any way. Otherwise, URLs get
extra language info added (e.g., /strings/[lang]) based on what is in the HTML element's lang attribute.

functionreadyCallback(){

// Safe to use localized.get() now...

}

var options ={ noCache:true, url:'/localized'}

localized.ready(options, readyCallback);

// NOTE: you could also call it like so:

// localized.ready(function(){...}); with no options.

getCurrentLang - a function that returns the current language defined in the HTML element of the page.