i18n made simple
I18nliner is I18n made simple.
No .js/yml translation files. Easy inline defaults. Optional keys. Easy pluralization. Wrappers for HTML-free translations.
I18nliner extends i18n-js, so you can add it to an already-internationalized app that uses it.
I18nliner lets you do stuff like this:
Best of all, you don't need to maintain translation files anymore; I18nliner will do it for you.
To install the command-line tools (for extracting/managing translations), use npm (see below).
Download the runtime extensions
and include them on the page after i18n.js (via
<script>, asset pipeline, etc).
npm install i18nliner --save
You'll need to shoehorn i18n.js into your app, which (as of this writing) is not CJS-compatible :-/, e.g.
// assuming you shoehorn this invar I18n = ;// add the runtime extensions"default"I18n;
Download the runtime extensions and use the requirejs shim config to add them (and i18n.js) to your app, e.g.
Instead of maintaining .js/.yml files and doing stuff like this:
Forget the translation file and just do:
Regular I18n options follow the (optional) default translation, so you can do the usual stuff (placeholders, etc.).
Sure, but you don't need to write them. Just run:
This extracts all default translations from your codebase and outputs them
Why waste time coming up with keys that are less descriptive than the default translation? I18nliner makes keys optional, so you can just do this:
I18nliner will create a unique key based on the translation (e.g.
'my_account'), so you don't have to. See
This can actually be a good thing, because when the
en changes, the key
changes, which means you know you need to get it retranslated (instead of
letting a now-inaccurate translation hang out indefinitely). Whether you want
to show "[ missing translation ]" or the
en value in the meantime is up to
var string = 'You can <a href="/new">lead</a> a new discussion or \<a href="/search">join</a> an existing one.';
You might say "No, I'd use handlebars". Bear with me here, we're trying to make this easy for you and the translators :). For I18n, you might try something like this:
var string = I18n;
This is not great, because:
So you might try this instead:
var string = I18n;
This isn't much better, because now you have HTML in your translations. If you want to add a class to the link, you have to go update all the translations. A translator could accidentally break your page (or worse, cross-site script it).
So what do you do?
I18nliner lets you specify wrappers, so you can keep HTML out the translations, while still just having a single string needing translation:
var string = I18n;
Default delimiters are increasing numbers of asterisks, but you can specify any string as a delimiter by using a object rather than an array.
I18nliner ensures translations, interpolated values, and wrappers all play
nicely (and safely) when it comes to HTML escaping. Wrappers are assumed
to be HTML-safe, so everything else that is unsafe will get
automatically escaped. If you are using i18n.js, you can hint that an
interpolation value is already HTML-safe via
I18n;"If you type <input> you get <input>"
If any interpolated value or wrapper is HTML-safe, everything else will be HTML- escaped.
Pluralization can be tricky, but i18n.js gives you some flexibility. I18nliner brings this inline with a default translation object, e.g.
Note that the
count interpolation value needs to be explicitly set when doing
If you just want to pluralize a single word, there's a shortcut:
This is equivalent to:
Ensures that there are no problems with your translate calls (e.g. missing interpolation values, reusing a key for a different translation, etc.). Go add this to your Jenkins/Travis tasks.
i18nliner check, and then extracts all default translations from your
codebase, merges them with any other translation files, and outputs them to
i18nliner export and creates a diff from a previous one (path or git
commit hash). This is useful if you only want to see what has changed since a
previous release of your app.
Imports a translated .json/.js file. Ensures that all placeholders and wrappers are present.
By default, the check and export tasks will look for inline translations in any .js files. You can tell it to always skip certain files/directories/patterns by creating a .i18nignore file. The syntax is the same as .gitignore, though it supports a few extra things.
If you only want to check a particular file/directory/pattern, you can set the
--only option when you run the command, e.g.
i18nliner check --only=/app/**/user*
I18nliner is backwards compatible with i18n.js, so you can add it to an established (and already internationalized) app. Your existing translation calls, keys and translation files will still just work without modification.
Copyright (c) 2015 Jon Jensen, released under the MIT license