Powerful and fast runtime internationalization (i18n) utility without dependencies.
- Flexible and easy to use getting translations by paths
- Nesting translation branches
- Extending branches with
@extend
directive - Defining branch fallbacks with
@any
directive - Defining branch root with
@root
directive - Reuse keys with in-translation
<[path]>
directive - Interpolation with in-translation
<=[param]>
directive
Using npm:
$ npm install mova
Returns translation for passed path. Path could be built with strings and arrays of strings. If the last argument is an object - it will be used as interpolation params object. Any other arguments will be ignored.
For example, all of this calls are equal:
mova('k1.k2.k3.k4.k5', { param: 'value' });
mova('k1', 'k2', 'k3', 'k4', 'k5', { param: 'value' });
mova('k1', 'k2', ['k3'], 'k4.k5', { param: 'value' });
mova('k1', ['k2', ['k3', 'k4']], 'k5', { param: 'value' });
mova('k1', ['k2', ['k3.k4']], 'k5', { param: 'value' });
mova('.', null, 'k1', NaN, ['k2', 'k3.k4'], {}, 'k5', 10, { param: 'value' });
Accepts language pack and pre-compiles it for better runtime performance.
Allows you to prepare language namespace for further usage.
For example, this call:
const t = mova.nameSpace('k1', 'k2', 'k3');
t('k4', 'k5');
Equals to:
mova('k1', 'k2', 'k3', 'k4', 'k5');
Alias for mova.nameSpace
method.
Allows you to interpolate passed params on passed string.
mova.interpolate('key1: <=key1>', { key1: 'value 1' }); // -> key1: value 1
interpolationFallback arg allows to define fallback which will be used if no value passed for some param. If not specified - such params will not be interpolated.
mova.interpolate('key1: <=key1>', {}, '-'); // -> key1: -
mova.interpolate('key1: <=key1>', {}); // -> key1: <=key1>
This method is used by mova
main function for value interpolation.
Interpolation fallback used by default. You can redefine it if necessary:
mova.interpolationFallback = '[no value]';
To use mova
for i18n you have to define language pack first.
Basically it's simple object with unlimited depth of nesting, like this:
{
"key1": "value 1",
"branch": {
"key1": "branch value 1",
"innerBranch": {
"key1": "inner branch value 1"
}
}
}
mova('branch.key1'); // -> 'branch value 1'
Above example is very simple while real applications might need more complex solutions like extending branches, defining fallback translations, defining branch root translations, referencing other translations or interpolation.
For this purposes mova
supports directives.
Allows you to define root translation for specific branch.
{
"branch": {
"@root": "Branch root"
}
}
mova('branch'); // -> 'Branch root'
@root
directive can not be used on translation root branch.
Allows you to define a fallback translation for specific branch.
{
"branch": {
"@any": "Branch fallback",
"innerBranch": {}
}
}
mova('branch.unknown.key'); // -> 'Branch fallback'
// Also works for branch root path
mova('branch'); // -> 'Branch fallback'
// But does not work for existing inner branches
mova('branch.innerBranch.unknown.key'); // -> 'branch.innerBranch.unknown.key'
Allows you to extends existing branch. This directive accepts chaining, so if you will extend a branch that is extending another branch, your result branch will contain translations from both those branches.
{
"branch1": {
"@root": "Branch root",
"k1": "branch 1, value 1",
"k2": "branch 1, value 2"
},
"branch2": {
"@extends": "branch1",
"k1": "branch 2, value 1"
},
"branch3": {
"@extends": "branch2",
"@root": "Branch 2 root"
}
}
mova('branch2'); // -> 'Branch root'
mova('branch2.k1'); // -> 'branch 2, value 1'
mova('branch2.k2'); // -> 'branch 1, value 2'
mova('branch3'); // -> 'Branch 2 root'
mova('branch3.k1'); // -> 'branch 2, value 1'
mova('branch3.k2'); // -> 'branch 1, value 2'
You also can extend from several branches using ,
as paths separator in @extends
directive:
{
"branch1": {
"k1": "value 1"
},
"branch2": {
"k2": "value 2"
},
"branch3": {
"@extends": "branch1, branch2"
}
}
mova('branch3.k1'); // -> 'value 1'
mova('branch3.k2'); // -> 'value 2'
@extends
directive has some restrictions:
- You can not extend any of parent branches.
- You can not create circular extending, i.e. no branch can be both dependency and dependent at the same time for any other branch.
Allows you to reuse your translations. [path]
should be replaced with absolute
path to translation or relative path to current branch prepended with .
{
"k1": "root value 1",
"branch": {
"@root": "branch root",
"k1": "branch value 1",
"k2": "reference - <k1>",
"k3": "reference - <.k1>",
"k4": "reference - <.>"
}
}
mova('branch.k2'); // -> 'reference - root value 1'
mova('branch.k3'); // -> 'reference - branch value 1'
mova('branch.k4'); // -> 'reference - branch root'
Allows you to interpolate some values in your translations.
{
"k1": "<=key1>",
"k2": "<k1> <=key2>"
}
mova('k2', { key1: 'val1', key2: 'val2' }); // -> 'val1 val2'
mova('k2', { key1: 'val1' }); // -> 'val1 -'
In second example <=key2>
param was replaced with mova.interpolationFallback
value
which is equal to -
by default.
mova
will pre-compile passed language pack before using it to increase runtime
translation performance.
So, for example, this language pack:
{
"k1": "value 1",
"base": {
"@root": "base root",
"k3": "base value 3",
"k4": "relative <.k1>"
},
"branch": {
"@extends": "base",
"@any": "branch fallback",
"k1": "branch <k1>",
"k2": "branch value 2 <=key>"
}
}
Will be pre-compiled to this:
{
"k1": "value 1",
"base": "base root",
"base.k3": "base value 3",
"base.k4": "relative base.k1",
"branch": "base root",
"branch.@any": "branch fallback",
"branch.k1": "branch value 1",
"branch.k2": "branch value 2 <=key>",
"branch.k3": "base value 3",
"branch.k4": "relative branch value 1"
}
So what happens during pre-compilation step:
- Resolve
@extends
directives - Resolve in-translation
<[path]>
directives with respect to@root
and@any
directives - Resolve
@root
directives - Flatten language pack to single level object with compiled paths as keys
Because of this pre-compilation mova
works very fast in runtime as its flow now very simple:
- Join passed path parts with
.
separator - Try to find direct value for this path or fallback for its branch
- Interpolate found value with passed named params
If no value will be found for passed path mova
will return this path as result.