@jochlain/translations
v2.0.0
Published
Translation module
Maintainers
Readme
Translation module
From a catalog of translations, translate your content with or not parameters.
Can work with Symfony translations structure in Node environment and/or with Webpack using Babel.
See how to integrate with :
Summary
Installation
npm install --save @jochlain/translationsUsage
const CATALOG = {
en: {
messages: {
hello: "Hi",
"translations.are.incredible": 'The translations are incredible.',
very: { compound: { key: "The compound key" } },
},
forms: {
"This field is required.": "This field is required."
},
},
es: {
messages: {
hello: "Holà",
"translations.are.incredible": 'Las traducciones son increíbles.',
very: { compound: { key: "La llave compuesta" } },
},
forms: {
"This field is required.": "Este campo es obligatorio.",
},
},
fr: {
messages: {
hello: "Bonjour",
"translations.are.incredible": "Les traductions sont incroyables.",
very: { compound: { key: "La clé composée" } },
},
forms: {
"This field is required.": "Ce champs est obligatoire.",
},
},
it: {
messages: {
hello: "Ciao",
"translations.are.incredible": 'Le traduzioni sono incredibili.',
very: { compound: { key: "La chiave composta" } },
},
forms: {
"This field is required.": "Questo campo è richiesto.",
},
},
};import Translator, { translate } from "@jochlain/translations";
const translator = Translator(CATALOG);
console.log(translator.translate('hello')); // => "Hi"
console.log(translator.translate('hello', null, null, 'fr')); // => "Bonjour"
// With unknown informations
console.log(translator.translate('hello', null, 'forms')); // => "hello"
console.log(translator.translate('hello', null, 'validators')); // => "hello"
console.log(translator.translate('hello', null, null, 'ar')); // => "hello"
// Compound key
console.log(translator.translate('very.compound.key')); // => "The compound key"
// Fake compound key
console.log(translator.translate('translations.are.incredible')); // => "The translations are incredible."
// Usage of with* helper
const translatorFormsEn = translator.withDomain('forms');
const translatorFormsFr = translatorFormsEn.withLocale('fr');
console.log(translatorFormsEn.translate('This field is required.')); // => "This field is required."
console.log(translatorFormsFr.translate('This field is required.')); // => "Ce champs est obligatoire."
console.log(translate({ en: 'Hello', fr: 'Bonjour' })); // => "Hello"
console.log(translate({ en: 'Hello', fr: 'Bonjour' }, null, 'fr')); // => "Bonjour"For more usage sample see Jest test
Intl integration
Intl installation
npm i -S intl-messageformat
Usage with Intl
import Translator from "@jochlain/translations";
import { IntlMessageFormat } from "intl-messageformat";
const formatter = { format: (message, replacements, locale) => (new IntlMessageFormat(message, locale).format(replacements)) };
const translator = Translator(CATALOG, { formatter });Questions and answers
Why ?
Because I can't found a simple and secured way to send translations to front shared by server.
Who ?
For little project directly or bigger project with babel macro.
- Load translations from JSON files
- Load translations from YAML files
Where ?
In a node / browser / compiled / SSR.
Documentation
Types
type ReplacementType = { [key: string]: number|string };
type FormatType = (message: string, replacements: ReplacementType, locale: string) => string;
type FormatterType = { format: FormatType };
type CatalogType = { [key: string]: string|CatalogType };
type TranslationType = { [locale: string]: { [domain: string]: CatalogType } };
type OptionsType = { locale?: string, domain?: string, formatter?: FormatterType };Constants
DEFAULT_DOMAIN="messages"
DEFAULT_LOCALE="en"Module
| Name | Type | Description | |------------------------------|-------------------------------------------|---------------------------------------------------------------------------------------| | default | Proxy<Translator> | If call like a function it calls create static method, else is the Translation class. | | DEFAULT_DOMAIN | string | Module constant | | DEFAULT_LOCALE | string | Module constant | | Translator | Proxy<Translator> | The default export of the module | | createTranslator | Function | Static method create | | formatMessage | Function | Default format method | | getCatalogValue | Function | Static method getCatalogValue | | mergeCatalogs | Function | Static method mergeCatalogs | | translate | Function | Static method translate |
Translator proxy
If is applied like below, it calls static method create. If is constructed like below, is calls the constructor.
import Translator from "@jochlain/translations";
const domain = 'messages';
const locale = 'en';
const catalogs = new Map();
catalogs.set('messages-en', { hello: 'Hello' });
const translations = { en: { messages: { hello: 'Hello' } } };
const translator_applied = Translator(translations, { domain, locale }); // call static method create.
const translator_constructed = new Translator(catalogs, { domain, locale }); // construct new instanceTranslator class
Members
| Name | Type | Default | Description |
|----------------|------------------------------------|--------------------------------------------------------------|----------------------------------------------|
| catalogs | Map<string, CatalogType> | [] | Translation catalogs |
| fallbackDomain | string | 'messages' | Default domain used in translate |
| fallbackLocale | string | 'en' | Default locale used in translate |
| formatter | FormatterType | { format } | Formate message with locale and replacements |
| translations | TranslationType | {} | Translation catalogs formatted as object |
Constructor
Parameters
| Name | Type | Default |
|----------|------------------------------------|-----------|
| catalogs | Map<string, CatalogType> | Empty Map |
| options | OptionsType | {} |
Return value
| Type | |---------------------------------| | Translator |
Static methods
Create Translator instance with another catalogs format and set fallback values.
Parameters
| Name | Type | Default | Description |
|--------------|---------------------------|---------|---------------------------------------------|
| translations | TranslationType | {} | Translation catalogs by locale and domains |
| options | OptionsType | {} | Options to set member default value |
Return value
| Type | Description | |---------------------------------|-----------------------| | Translator | A translator instance |
Browse catalog to find value assigned to key
Parameters
| Name | Type | |---------|----------------------------------------| | catalog | CatalogType | undefined | | key | string |
Return value
| Type | Description | |--------|----------------------------------------------------------------------| | string | The value in the catalog attached to the key or the key if not found |
Format a key from domain and locale.
Parameters
| Name | Type | |--------|--------| | domain | string | | locale | string |
Return value
| Type | Description | |--------|-------------------| | string | The formatted key |
Deep merge many catalogs
Parameters
| Name | Type | |---------|-------------------------| | target | ?CatalogType | | sources | CatalogType[] |
Return value
| Type | Description | |-----------------------|-----------------------------------| | CatalogType | A catalog with deep merged values |
Get domain and locale from key.
Parameters
| Name | Type | |------|--------| | key | string |
Return value
| Type | Description | |------------------|---------------------------| | [string, string] | The domain and the locale |
Translate a message from a simple catalog
Parameters
| Name | Type | Default | |--------------|------------------------------|--------------------------------------------------------------| | catalog | { [locale: string]: string } | {} | | replacements | ?ReplacementType | {} | | locale | string | DEFAULT_LOCALE | | formatter | FormatterType | { format } |
Return value
| Type | Description | |--------|------------------------| | string | The translated message |
Methods
Add a catalog to translations map
Parameters
| Name | Type | Default |
|---------|-----------------------|---------------------------------|
| catalog | CatalogType | {} |
| locale | string | this.fallbackLocale |
| domain | string | this.fallbackDomain |
Return value
| Type | Description | |---------------------------------|------------------------------------------| | Translator | The translator instance to chain methods |
Get the catalog attached to domain and locale in catalogs map.
If locale is like en_US it looks first for a en_US catalog and if not looks for a en catalog.
Parameters
| Name | Type | Default | |---------|--------|---------------------------------| | locale | string | this.fallbackLocale | | domain | string | this.fallbackDomain |
Return value
| Type | Description | |----------------------------------------|-------------------------------------------------------| | CatalogType | undefined | The catalog of messages attached to domain and locale |
Get all domains fill in catalogs map
Return value
| Type | Description | |----------|-------------| | string[] | The domains |
Get all locales fill in catalogs map
Return value
| Type | Description | |----------|-------------| | string[] | The locales |
Get message attached to key in catalog attached to domain and locale in catalogs.
See getCatalog and getCatalogValue
Parameters
| Name | Type | Default | |--------|--------|---------------------------------| | key | string | none | | locale | string | this.fallbackLocale | | domain | string | this.fallbackDomain |
Return value
| Type | Description | |--------|---------------------------------------------| | string | Message attached to key or key if not found |
Get messages attached to key
Parameters
| Name | Type | Default | |--------|--------|---------------------------------| | key | string | none | | domain | string | this.fallbackDomain |
Return value
| Type | Description | |------------------------------|------------------------------------| | { [locale: string] :string } | A collection of messages by locale |
Set the fallbackDomain member
Parameters
| Name | Type | Default | |--------|--------|------------------------------| | domain | string | DEFAULT_DOMAIN |
Return value
| Type | Description | |---------------------------------|------------------------------------------| | Translator | The translator instance to chain methods |
Set the fallbackLocale member
Parameters
| Name | Type | Default | |--------|--------|------------------------------| | locale | string | DEFAULT_LOCALE |
Return value
| Type | Description | |---------------------------------|------------------------------------------| | Translator | The translator instance to chain methods |
Set the formatter member
Parameters
| Name | Type | Default | |-----------|-------------------------|--------------------------------------------------------------| | formatter | FormatterType | { format } |
Return value
| Type | Description | |---------------------------------|------------------------------------------| | Translator | The translator instance to chain methods |
Set the formatter member
Parameters
| Name | Type | Default | |--------------|---------------------------|----------------------------| | translations | TranslationType | The translations to append |
Return value
| Type | Description | |---------------------------------|------------------------------------------| | Translator | The translator instance to chain methods |
Clone instance with fallbackDomain domain parameter
Parameters
| Name | Type | |--------|--------| | domain | string |
Return value
| Type | Description | |---------------------------------|---------------------------| | Translator | A new translator instance |
Clone instance with formatter
Parameters
| Name | Type | |-----------|-------------------------| | formatter | FormatterType |
Return value
| Type | Description | |---------------------------------|---------------------------| | Translator | A new translator instance |
Clone instance with fallbackLocale locale parameter
Parameters
| Name | Type | |--------|--------| | locale | string |
Return value
| Type | Description | |---------------------------------|---------------------------| | Translator | A new translator instance |
Clone instance with domain, formatter, locale.
Parameters
| Name | Type | Default | |-----------|---------------|---------------------------------| | domain | string | this.fallbackDomain | | locale | string | this.fallbackLocale | | formatter | FormatterType | this.formatter |
Return value
| Type | Description | |---------------------------------|---------------------------| | Translator | A new translator instance |
Default format method
By default, format method search each replacement key with a RegExp and replace them by their values.
That's the next part I'm going to look at.
function format(message: string, replacements: ReplacementType, locale: string = DEFAULT_LOCALE) {
let result = message;
for (let keys = Object.keys(replacements), idx = 0; idx < keys.length; idx++) {
result = result.replace(new RegExp(`${keys[idx]}`, 'g'), String(replacements[keys[idx]]));
}
return result;
}