diff --git a/README.md b/README.md index efbfe8c..456ba54 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ Minimalist gettext style i18n for JavaScript ## Features -- Pluralization support (ngettext style) -- Supports React components as interpolations -- Optional markdown support +- [Supports React components as interpolations](#interpolations) +- [Pluralization support](#pluralization) (ngettext style) +- [markdown support](#markdown) - Compatible with [webpack po-loader](https://github.com/perchlayer/po-loader) - Comes with scripts for extracting translation strings from JavaScript (Babel) sources and updating .pot and .po files @@ -72,7 +72,7 @@ init(getLangLoader, config).then(() => { // promise will be resolved when the translation bundle for the active locale has been loaded alert(i18n('Hello world!')) // >> Hello world! - + // switch to another language setLocale('de').then(() => { alert(i18n('Hello world!')) @@ -80,3 +80,60 @@ init(getLangLoader, config).then(() => { }) }) ``` + +### Interpolations + +Interpolations make it easier to include variable content into messages without confusing translators. +For instance, if you want to include a computed number in a message, you can do it like this: + +```javascript +const available = 100 +const count = available / 10 + +i18n('Showing __count__ of __available__ entires.', { count, available }) +``` + +For your convenience interpolations also support React elements. +So you can do things like: + +```jsx +i18n('Contact __supportLink__', { + supportLink: Support, +}) +``` + +### Pluralization + +Often times you get to the situation that the same message needs to look slightly different depending on whether you talk about one or more things. +Handling this can add quite a lot of unnecessary code. +You can circumvent this with the built in support for pluralizations. + +```javascript +i18n('Showing __count__ item', 'Showing __count__ items', { count }) +``` + +To use this feature simply pass two different translations to the `i18n` function. +The first string is used for the singular case and the second one for the plural case. +Note that you **have** to hand in a variable called count. +This variable is used to decide which version of the translation to choose. + +### Message context + +Sometimes the same translation key can have different meanings based on the context in which is it used. +Message context offers a solution to this problem. +If you specify the optional `context` parameter you can have different translations for the same translation key. + +```javascript +i18n('Ok', { context: 'button' }) +``` + +### Markdown + +Another convenience of `signavio-i18n` is the optional support for markdown in translations. +By default this is turned off, but you can activate it by setting the `markdown` option to `true`. + +```javascript +i18n('I want _this_ to be **bold**', { + markdown: true, +}) +``` diff --git a/specs/i18n.spec.js b/specs/i18n.spec.js index 3188dd2..6699f11 100644 --- a/specs/i18n.spec.js +++ b/specs/i18n.spec.js @@ -11,7 +11,7 @@ function getLangLoader(locale) { // A runtime exception will be throw every time that the requested locale file // cannot be found. Webpack uses a regular expression to build all locales as // separate bundles. - // eslint-disable-next-line import/no-dynamic-require + // eslint-disable-next-line global-require,import/no-dynamic-require return require(`bundle?lazy!./locales/${locale}.po`) } @@ -43,7 +43,6 @@ describe('i18n', () => { }) describe('#translate', () => { - it('should return a plain string whenever possible', () => { const t = i18n('This is a __test__.', { test: 'success' }) expect(t).to.be.a('string') @@ -125,23 +124,23 @@ describe('i18n', () => { }) it('should consider the context option, if provided', (done) => { - setLocale('de_DE') + setLocale('de_DE') - init(getLangLoader, config).then(() => { - expect(i18n('Export', {context: 'button label'})).to.equal('Exportieren') + init(getLangLoader, config).then(() => { + expect(i18n('Export', { context: 'button label' })).to.equal('Exportieren') - done() - }).catch(done) + done() + }).catch(done) }) it('should use the translation key without any msgctxt, if no msgctxt is provided', (done) => { - setLocale('de_DE') + setLocale('de_DE') - init(getLangLoader, config).then(() => { - expect(i18n('Export')).to.equal('Exportiere') + init(getLangLoader, config).then(() => { + expect(i18n('Export')).to.equal('Exportiere') - done() - }).catch(done) + done() + }).catch(done) }) }) }) diff --git a/src/translate.js b/src/translate.js index 670b53d..7e624fb 100644 --- a/src/translate.js +++ b/src/translate.js @@ -26,7 +26,7 @@ export default (singleton) => function translate(text, plural, options) { finalOptions = { ...defaultOptions, ...finalOptions, - context: finalOptions && finalOptions.context ? finalOptions.context + '\u0004' : '', + context: finalOptions && finalOptions.context ? `${finalOptions.context}\u0004` : '', } const [