Fork me on GitHub

BabelFish - human friendly i18n for javascript

Build Status

Internationalisation with easy syntax for node.js. Classic solutions use multiple phrases for plurals. But we define plurals inline - that's more compact, and easier to maintain. Also, phrases are grouped into nested scopes, like in Ruby.

We support all pluralisation rules from unicode CLDR, version 2.0.1.

Installation

node.js:

$ npm install babelfish

browser:

$ bower install babelfish

You need es5-shim for old browsers compatibility.

Phrases Syntax

  • #{varname} Echoes value of variable
  • ((Singular|Plural1|Plural2)):count Plural form

example:

  • А у меня в кармане #{nails_count} ((гвоздь|гвоздя|гвоздей)):nails_count

You can also omit anchor variable for plurals, by default it will be count. Thus following variants are equal:

  • I have #{count} ((nail|nails))
  • I have #{count} ((nail|nails)):count

Also you can use variables in plural parts:

  • I have ((#{count} nail|#{count} nails))

Need special zero form or overwrite any specific value? No problems:

  • I have ((=0 no nails|#{count} nail|#{count} nails))
Escape chars

If you need #{, ((, | or )) somewhere in text, where it can be considered as markup part - just escape them with \.

Example with YAML

As BabelFish flatten scopes, it's really fun and nice to store translations in YAML files:

---
ru-RU:
  profile: Профиль
  forums: Форумы
  apps:
    forums:
      new_topic: Новая тема
      last_post:
        title : Последнее сообщение
        by : от
  demo:
    apples: На столе лежит #{count} ((яблоко|яблока|яблок))

Usage

// Create new instance of BabelFish with default language/locale: 'en-GB'
var BabelFish = require('babelfish');
var i18n = new BabelFish('en-GB');


// Fill in some phrases
i18n.addPhrase('en-GB', 'demo.hello',         'Hello, #{user.name}.');
i18n.addPhrase('en-GB', 'demo.conv.wazup',    'Whats up?');
i18n.addPhrase('en-GB', 'demo.conv.alright',  'Alright, man!');
i18n.addPhrase('en-GB', 'demo.coerce',        'Total: #{count}.');

i18n.addPhrase('ru-RU', 'demo.hello',         'Привет, #{user.name}.');
i18n.addPhrase('ru-RU', 'demo.conv.wazup',    'Как дела?');

i18n.addPhrase('uk-UA', 'demo.hello',         'Здоровенькі були, #{user.name}.');


// Set locale fallback to use the most appropriate translation when possible
i18n.setFallback('uk-UA', 'ru-RU');


// Translate
var params = {user: {name: 'ixti'}};

i18n.t('ru-RU', 'demo.hello', params);  // -> 'Привет, ixti.'
i18n.t('ru-RU', 'demo.conv.wazup');     // -> 'Как дела?'
i18n.t('ru-RU', 'demo.conv.alright');   // -> 'Alright, man!'

i18n.t('uk-UA', 'demo.hello', params);  // -> 'Здоровенькі були, ixti.'
i18n.t('uk-UA', 'demo.conv.wazup');     // -> 'Как дела?'
i18n.t('uk-UA', 'demo.conv.alright');   // -> 'Alright, man!'

// When params is number or strings, it will be coerced to
// `{ count: XXX, value: XXX }` - use any of those in phrase.
i18n.t('en-GB', 'demo.coerce', 5);      // -> 'Total: 5.'


// You may wish to "dump" translations to load in browser later
// Dump will include all fallback translations and fallback rules
var locale_dump = i18n.stringify('ru-RU');

var i18n_new = require('babelfish')('en-GB'); // init without `new` also works
i18n_new.load(locale_dump);


// Use objects instead of strings (object/array/number/boolean) - can be
// useful to prepare bulk data for external libraries.
// Note, only JSON-supported types are ok (no date & regex)
i18n.addPhrase('en-GB', 'demo.boolean',  true);
i18n.addPhrase('en-GB', 'demo.number',   123);
i18n.addPhrase('en-GB', 'demo.array',    [1, 2, 3]);
// fourth param required for hashes (objects) to disable flattening,
// other types are autodetected
i18n.addPhrase('en-GB', 'demo.array',    { foo:1, bar:"2" }, false);

License

View the LICENSE file (MIT).

class

BabelFish

Description

Internalization and localization library that makes i18n and l10n fun again.

Example
var BabelFish = require('babelfish'),
    i18n = new BabelFish();

or

var babelfish = require('babelfish'),
    i18n = babelfish();

Constructor

constructor

BabelFish.new

    • new BabelFish([defaultLocale = "en"])

Initiates new instance of BabelFish.

Note! you can omit new for convenience, direct call will return new instance too.

instance method

BabelFish#addPhrase

    • BabelFish#addPhrase(locale, phrase, translation[, flattenLevel])
    • locale
      • String
    • Locale of translation

    • phrase
      • String
      • Null
    • Phrase ID, e.g. apps.forum

    • translation
      • String
      • Object
      • Array
      • Number
      • Boolean
    • Translation or an object with nested phrases, or a pure object.

    • flattenLevel
      • Number
      • Boolean
    • Optional, 0..infinity. Infinity by default. Define "flatten" deepness for loaded object. You can also use true as 0 or false as Infinity.

Flatten & using JS objects

By default all nested properties are normalized to strings like "foo.bar.baz", and if value is string, it will be compiled with babelfish notation. If deepness is above flattenLevel OR value is not object and not string, it will be used "as is". Note, only JSON stringifiable data should be used.

In short: you can safely pass Array, Number or Boolean. For objects you should define flatten level or disable it compleetely, to work with pure data.

Pure objects can be useful to prepare bulk data for external libraries, like calendars, time/date generators and so on.

Example
i18n.addPhrase('ru-RU',
  'apps.forums.replies_count',
  '#{count} %{ответ|ответа|ответов}:count в теме');

// equals to:
i18n.addPhrase('ru-RU',
  'apps.forums',
  { replies_count: '#{count} %{ответ|ответа|ответов}:count в теме' });
instance method

BabelFish#hasPhrase

    • BabelFish#hasPhrase(locale, phrase)
      • Boolean
    • locale
      • String
    • Locale of translation

    • phrase
      • String
    • Phrase ID, e.g. app.forums.replies_count

    • noFallback
      • Boolean
    • Disable search in fallbacks

Returns whenever or not there's a translation of a phrase.

instance method

BabelFish#setFallback

    • BabelFish#setFallback(locale, fallbacks)
    • locale
      • String
    • Target locale

    • fallbacks
      • Array
    • List of fallback locales

Set fallbacks for given locale.

When locale has no translation for the phrase, fallbacks[0] will be tried, if translation still not found, then fallbacks[1] will be tried and so on. If none of fallbacks have translation, default locale will be tried as last resort.

Errors
  • throws Error, when locale equals default locale
Example
i18n.setFallback('ua-UK', ['ua', 'ru']);
instance method

BabelFish#stringify

    • BabelFish#stringify(locale)
      • String
    • locale
      • String
    • Locale of translation

Returns serialized locale data, uncluding fallbacks. It can be loaded back via load() method.

instance method

BabelFish#t

    • BabelFish#t(locale, phrase[, params])
      • String
instance method

BabelFish#translate

    • BabelFish#translate(locale, phrase[, params])
      • String
    • locale
      • String
    • Locale of translation

    • phrase
      • String
    • Phrase ID, e.g. app.forums.replies_count

    • params
      • Object
      • Number
      • String
    • Params for translation. Number & String will be coerced to { count: X, value: X }

Example
i18n.addPhrase('ru-RU',
   'apps.forums.replies_count',
   '#{count} ((ответ|ответа|ответов)) в теме');

// ...

i18n.translate('ru-RU', 'app.forums.replies_count', { count: 1 });
i18n.translate('ru-RU', 'app.forums.replies_count', 1});
// -> '1 ответ'

i18n.translate('ru-RU', 'app.forums.replies_count', { count: 2 });
i18n.translate('ru-RU', 'app.forums.replies_count', 2);
// -> '2 ответa'
Aliased as: