Skip to content

Instantly share code, notes, and snippets.

@morhekil
Last active August 9, 2016 14:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save morhekil/a0ebadf392ad4dc51dd87dfef3238fe3 to your computer and use it in GitHub Desktop.
Save morhekil/a0ebadf392ad4dc51dd87dfef3238fe3 to your computer and use it in GitHub Desktop.
I grew frustrated trying to deal with FormatJS, react-intl et al, and wrote a simple wrapper around polyglot, numeral and moment js to localise a React app.
// Simple i18n wrapper around polyglot, numeral and moment libraries:
// http://airbnb.io/polyglot.js/
// http://numeraljs.com/
// http://momentjs.com/
//
// This is to achieve goals:
// 1. Have a locale message storage that can be decomposed into subsets,
// and passed down the dependency chain. Think providing a subset of locale
// strings to child components.
// 2. Centralise configuration, and normalise API of both moment and numeral
// libraries.
//
// Usage:
//
// import i18n from './i18n';
// const locale = i18n('ru', { greetings: { hello: 'Привет, %{username}!' } });
// const greets = locale.ns('greetings');
// const string = greets.t('hello', { username: 'Einstein' });
// const number = greets.numeral.set(100000).format('0,000.00');
// const datetime = greets.moment.set('2016-01-01').format('LLLL');
//
// Subset and the original objects are functionally equivalent, and either one
// can be used for number and time formatting - making it easy to use subset
// objects injected as dependencies.
//
// See tests below for more usage examples.
import Polyglot from 'node-polyglot';
import moment from 'moment';
import numeralRU from 'numeral/languages/ru';
import numeral from 'numeral';
numeral.language('ru', numeralRU);
const i18n = (locale, phrases) => {
const polyglot = new Polyglot({ locale, phrases });
const localiser = (prefix) => ({
locale,
numeral: (x) => numeral.language(locale) && numeral(x),
moment: (x) => moment(x).locale(locale),
toString() { return prefix; },
t(key, opts) { return polyglot.t(`${prefix}${key}`, opts); },
ns(str) { return localiser(`${prefix}${str}.`); }
});
return localiser('');
};
export default i18n;
import { test } from 'ava';
import i18n from '../i18n';
test('basic translation', t => {
const locale = i18n('ru', { boo: 'Boo Boo' });
t.is(locale.t('boo'), 'Boo Boo');
});
test('namespace extraction', t => {
const locale = i18n('ru', { boo: { woo: { moo: 'Moo Moo' } } });
const woo = locale.ns('boo').ns('woo');
t.is(woo.t('moo'), 'Moo Moo');
});
test('interpolation', t => {
const locale = i18n('ru', { boo: 'Hi there %{username}' });
t.is(locale.t('boo', { username: 'mrfreeman' }), 'Hi there mrfreeman');
});
test('pluralization', t => {
const locale = i18n('ru', { boo: 'One thing |||| Many things' });
t.is(locale.t('boo', 1), 'One thing');
t.is(locale.t('boo', 2), 'Many things');
});
test('numeral js integration', t => {
// note the order - numeral only has a global language,
// so we can't mix it as we can with momentjs
const ru = i18n('ru', { });
const en = i18n('en', { });
t.is(ru.numeral(10000).format('0,000.00'), '10 000,00');
t.is(en.numeral(10000).format('0,000.00'), '10,000.00');
});
test('moment js integration', t => {
const ru = i18n('ru', { });
const en = i18n('en', { });
t.is(ru.moment('2016-01-01').format('L'), '01.01.2016');
t.is(en.moment('2016-01-01').format('L'), '01/01/2016');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment