reactive-i18n

1.0.2 • Public • Published

Reactive I18N

Reactive-i18n allows you to, reactivelly, deal with Internacionalization in your pages and apps.

With it, you create multiple dictionaries and use them in your components in a very, very ease, intuitive, readable and mantainable way. It even works with plurals, variables, lists and fallbacks.

See it working in this live demo. And see its source here

Installing it

npm install reactive-i18n

Importing it

First, you import both I18N and Label

import I18N, { Label } from 'reactive-i18n'
// OR
import { I18N, Label } from 'reactive-i18n'

Then, you may import your dictionaries (to be descibre in chapter Dictionaries):

import myDictionary from './my-dictionary.js'

You may use as many as you want.

Scope

You may specify a given scope for making use of a dictionary or language, like so:

    [...]
    render() {
        return <I18N
        use={myDictionary}
        lang={this.state.lang}>
            // your content goes here
        </I18N>
    }
    [...]

If you have more dictionaries to be used in the same scope, simply pass an Array in the use property.

Terms

Inside any scope, you may use the Label.

    [...]
    render() {
        return <I18N
        use={myDictionary}
        lang={this.state.lang}>
        <div>
            [...]
            <Label term='UserNameAndSurname' />
            [...]
        </div>
        </I18N>
    }
    [...]

It will look for the term UserNameAndSurname in all the dictionaries in the current scope, that bes match with the lang in the current scope.

Interestingly enough, a warning will be shown when a term is not found. But also, the term will be treated before being shown on the screen. The example above would become User name and surname...not translated, but better for users in case you forgot to translate any term in your dictionaries.

Dictionaries

Dictionaries are just an object.
They have an id, a langs object and may have a version.

const dictionary = {
    id: 'myDictIdentifier',
    version: '1',
    langs: {
        // ...
    }
}
export default dictionary

Dictionary's langs

This is an object containing all the languages you will support, and each language, all the terms, like this:

const dictionary = {
    id: 'myDictIdentifier',
    version: '1',
    langs: {
        en: {
            UserNameAndSurname: 'Full name'
        },
        es: {
            UserNameAndSurname: 'Nombre completo'
        }
    }
}
export default dictionary

And that is it. This is the basic usage.

Plural and singular

If you want to use different strings for plural or string, first, you need to say the number. You do that using the val property:

    <Label
        term='friends'
        val={this.state.groceries.length} />

And, in the dictionary, you simple use an array with 2 strings, instead of one:

    // ...
    langs: {
        en: {
            friends: [
                'Friend',
                'Friends'
            ]
        },
        es: {
            friends: [
                'Amigo',
                'Amigos'
            ]
        }
    }
    // ...

Variables

You can send some variables, and use them as in template strings, with the ${varName} syntax.
Send variables like this:

    <Label
        term='hi'
        person={'Felipe'} />

In dictionary, you can now access person:

    // ...
    langs: {
        en: {
            hi: 'Hi ${person}'
        },
        es: {
            hi: 'Hola ${person}'
        }
    }
    // ...

Lists

You can send lists, as well.

    <Label
        term='friends'
        friends={['Felipe', 'Jaydson', 'Gabe']} />

In dictionary:

    // ...
    langs: {
        en: {
            friends: 'Hi ${friends}'
        },
        es: {
            friends: 'Hola ${friends}'
        }
    }
    // ...

By default, all the items in the list will be glued by ,.
BUT...you can change that by specifying the joints in your dictionary:

    // ...
    langs: {
        en: {
            joints: ['', ' and ', ' or '],
            friends: 'Hi ${friends}'
        },
        es: {
            joints: ['', ' y ', ' o '],
            friends: 'Hola ${friends}'
        }
    }
    // ...

Now, the output in english would be Hi Felipe, Jaydson and Gabe, and the output in spanish would be Hola Felipe, Jaydson y Gabe.

Change the jointType to get the or.

    <Label
        term='friends'
        jointType='or'
        friends={['Felipe', 'Jaydson', 'Gabe']} />

The jointType may be or, and (default) or none (will use only ,)

You may even combine plural with your variables:

    <Label
        term='friends'
        val={this.state.friends.length}
        friends={this.state.friends} />

And, in dictionary:

    // ...
    langs: {
        en: {
            joints: ['', ' and ', ' or '],
            friends: [
                'Hello my only friend, ${friends}',
                'Hello all my ${val} friends ${friends}'
            ]
        },
        es: {
            joints: ['', ' y ', ' o '],
            friends: [
                'Hola mi único amigo, ${friends}',
                'Hola mis ${val} amigos ${friends}'
            ]
        }
    }
    // ...

Global / World

You may define some global terms...something that all (or most) of languages share in common.

For exampe:

    <Label
        term='dateFormat'
        day={19}
        month={'07'}
        year={1985} />
    // ...
    langs: {
        world: {
            dateFormat: '${day}/${month}/${year}'
        },
        'en-US': {
            dateFormat: '${month}/${day}/${year}'
        }
    }
    // ...

Different files for each language

Once the scope accepts multiple dictionaries, you can simply add different dictionaries there, each one, containing a single language.

    [...]
    render() {
        return <I18N
        use={[myEnDict, myEsDict, myPtDict]}
        lang={this.state.lang}>
            // your content goes here
        </I18N>
    }
    [...]

Fallback language

By default, it will follow this pattern.
If you specify the lang pt-BR, it will look for the terms there.
If the term is not found, then looks for it in any dictionary in pt.
If not found yet, looks for it in world.

But you may specify the fallbackLang for the scope, changing the behavior of the second step.

    [...]
    render() {
        return <I18N
        use={[myEnDict, myEsDict, myPtDict]}
        lang='pt-BR'
        fallbackLang='en'>
            // ...
        </I18N>
    }
    [...]

The fallbackLang property also accepts none. In this case, if the term is not found in any dictionary, no worning will be triggered and will not show anything on the screen for that term.

Technical table

Component

In your react components:
(* means mandatory)

Element Prop Val
use* Object or array
className A className, so you can customize it
lang* String, the language itself, like en or en-US
fallbackLang String, the language to be used as fallback, like en or en-US If none, the string will be ommited in case it was not found in any dictionary
className A className, so you can customize it
term* The term to be found in dictionaries
val Used to decide if it is plural or singular
jointType Used to know how to join lists with their last item. May be 'and', 'or' or 'none (default is 'and')
anyOtherProp Any other property will be passed to be used as variables

Dictionary

In your dictionaries:
(* means mandatory)

Element Prop Val
DictionaryObj id* An id for the dictionary
DictionaryObj version A version for the dictionary
DictionaryObj langs The languages object containing the languages and their terms
langs world A fallback for terms not found specialized in other languages. May be used for shared terms
langs langId Any language id, like en or en-US. Its value must be an Object
langObject joints An array with three items: the coma, the and and the or representations for lists
langObject terms May be a String for that term in the given language, or an Array with two items, the first for the singular value, the second for the plural representation of the value

Package Sidebar

Install

npm i reactive-i18n

Weekly Downloads

1

Version

1.0.2

License

MIT

Last publish

Collaborators

  • felipenmoura