i18n-core
i18n-core is a no-fuzz Node.js
implementation of i18n. It doesn't connect to express or any other fancy Node
framework and is extensible where it needs to be and allows to reduce the
complexity of other i18n implementations (thus the name).
It implements basic variable replacements in the mustache and sprintf manner.
Installation
To use i18n-core all you need to do is install it using npm
npm i i18n-core --save
Usage
var i18n_core = require('i18n-core')
var i18n = i18n_core({greeting: 'hello!'})
i18n.__('greeting')
To have different namespaces for different languages you can get a prefixed
translations using .section()
.
var i18n = i18n_core({
en: { greeting: 'hello!' },
de: { greeting: 'guten tag!' }
})
var en = i18n.section('en')
en.__('greeting')
var de = i18n.section('de')
de.__('greeting')
Note: .section(<section>)
is the same thing as .prefix(<section> + '.')
Lookups
The system is based on lookup
implementations that allow the system to use
different sources to get its strings from. The examples before used an object
and because of this the former example would be equal to:
var i18n = i18n_core(require('i18n-core/lookup/object')({greeting: 'hello!'}))
If you were to pass in a string to i18n-core
instead like this:
var i18n = i18n_core('./')
Then it would be equal the primitive file-system lookup same like this:
var i18n = i18n_core(require('i18n-core/lookup/fs')('./'))
You can pass in your own strategy by given an object to the constructor that
contains a "get"-method:
var i18n = i18n_core({
get: function (key) {
return null
}
})
In case you need to have several strategies that need to be chained you can use
the chain lookup:
var i18nChain = require('i18n-core/lookup/chain')
var i18nObject = require('i18n-core/lookup/object')
var i18n = i18n_core(i18nChain(i18nObject({a: 'x'}), i18nObject({a: 0, b: 1})))
i18n.__('a')
i18n.__('b')
In case you have an i18n
object that you want to use as lookup for another
i18
object you can extend them:
var i18nExtend = require('i18n-core/lookup/extend')
var i18nObject = require('i18n-core/lookup/object')
var i18nA = i18n({a: 'x'})
var i18nB = i18n(i18nExtend(i18nA, i18nObject({
b: 1
})))
i18n.__('a')
i18n.__('b')
Substitution
i18n-core does implement basic placeholder replacements like:
en.__('%s is cool', 'he')
following the logic of sprintf
.
It also offers mustache
-like pattern
replacement like this:
en.__('{{name}} are cool too', {name: 'you'})
Substitution variants
By default i18n-core
does not have any dependencies and the default
substitution is mustache
-like and sprintf
-like with limited compatibility.
Note: Without mustache
and sprintf
installed, it will use
require('i18n-core/simple')
In order to get full compatibility you can simply install the peer dependency.
npm i mustache sprintf --save
Note: With mustache
and sprintf
installed, it will use
require('i18n-core/full')
It is furthermore possible to customize the formatting by specifying own
implementations:
var i18n_core = require('i18n-core')
i18n_core.mustache = require('mustache')
i18n_core.vsprintf = require('sprintf').vsprintf
Advanced Namespaces
It is possible to chain translation prefixes like this:
var at = i18n_core({de:{at: {hello: 'Zewas!'}}}).section('de').section('at')
at.__('hello')
and you can also change the chain if you want to.
var translate = i18n_core({
de: {title: 'Meine Webseite'},
en: {title: 'My Website'}
}).section('de', true)
translate.__('title')
translate.changeSection('en')
translate.__('title')
To prevent malicious use the changing of the section is prevented unless you
pass a true
flag to it.
In some instances it is necessary to know in advance if a key has a value or
not, in this case you can use has
.
var translate = i18n_core({title: 'My Website'})
translate.has('title')
translate.has('subtitle')
Additionally, for module development, its possible to access the raw data
using raw
:
var translate = i18n_core({no: {val: 5}})
translate.raw('no')
Listening to changes
Since you can change translation nodes it is, in an interactive environment,
good to have a way to be informed about changes. i18n-core
has a very
light-weight and fast event implementation tailored to the process.
const parent = i18n_core({
de: {
site: {
title: 'Meine Webseite'
}
},
en: {
site: {
title: 'My Website'
}
}
}).section('de', true)
const translate = parent.section('site')
translate.__('title')
translate.on('contextChange', function () {
translate.__('title')
})
parent.changeSection('en')
Absolute Lookups
i18n-core
supports the use of absolute roots. Absolute roots allow to lookup
entries in absolute locked roots rather than the given level.
var translate = i18n_core({
title: 'Meine Webseite',
sectionA: {
title: 'Lebenslauf'
}
})
var sub = translate.section('sectionA')
sub('title')
sub.abs('title')
This allows to crate things like footers where you can pass one section to a
module and it is still able to access absolute code.
However, this also creates the problem that subsections (for languages) can be
escaped from. In order to prevent that, you can lock the absolute root to
.lock()
. You can lock any section and any subsequent sections will get the
same root.
var translate = i18n_core({
de: {
title: 'Meine Webseite',
sectionA: { title: 'Lebenslauf' }
},
en: {
title: 'My Website',
sectionA: { title: 'Curriculum Vitae' }
}
})
var lang = translate
.section('de', true)
.lock()
var sub = lang.section('sectionA')
sub('title')
sub.abs('title')
lang.changeSection('en')
sub('title')
sub.abs('title')
Prefixing every absolute lookup with abs
can get tedious that is why there is
also the possibility to use absSection
that, like section
, returns a new
translation object where every call assumes a particular absolute section.
var translate = i18n_core({
en: {
sectionA: {
title: 'Curriculum Vitae'
},
menu: {
about: 'About Me'
}
}
})
var lang = translate.section('en', true).lock()
var sectionA = lang.section('sectionA')
sectionA('title')
var menu = sectionA.absSection('menu')
menu('about')
For your convenience there is also the .root()
alias for .absSection('')
.
Core API's
The default API is made to provide a simple solutions to common problems but
i18n-core
also offers a reduced, faster API without conveniences. You can get
access to the core by using require('i18n-core/core')
.
var core = require('i18n-core/core')({
get: function lookupValue (key) {
return
}
}, function translate (value, fallbackKey, namedArgs, args) {
})
core.get(key)
core.has(key)
core.translate(key, namedArgs, args)
core.translateFirst(keys, fallbackKey, namedArgs, args)
core.prefix(prefix, allowModification)
core.absPrefix(prefix, allowModification)
core.changePrefix(prefix)
core.lock(locked)
core.absRoot
core.parent
core.translator
core.currentPrefix
core.on(type, handler)
core.off(type, handler)
Outro
If you have any questions, please post them as issue, thanks!