UNPKG

@owja/i18n

Version:

lightweight internationalization library for javascript

174 lines (137 loc) 6.19 kB
![OWJA! i18n](resources/owja-i18n-logo.png) [![npm version](https://img.shields.io/npm/v/@owja/i18n.svg)](https://badge.fury.io/js/%40owja%2Fi18n) [![codecov](https://codecov.io/gh/owja/i18n/branch/master/graph/badge.svg)](https://codecov.io/gh/owja/i18n) [![Build Status](https://travis-ci.org/owja/i18n.svg?branch=master)](https://travis-ci.org/owja/i18n) [![size](https://img.badgesize.io/https://unpkg.com/@owja/i18n/index.module.js.svg?compression=brotli&label=size)](https://unpkg.com/@owja/i18n/index.module.js) This is a lightweight internationalization library which is in early **alpha** state. This means it is work in progress, unstable, can contain bugs and the API can change until first stable release. ### Features * lightweight bundle size **~1 kb** (brotli compressed, without plugins) * no global state * it is made with dependency injection in mind * Build-in support for plurals, interpolation and context * uses Intl.Locale and Intl.PluralRules under the hood * Extendable with plugins ##### What does it not have and why? * No loading mechanism. Nowadays we have dynamic imports and fetch and both can do this job perfectly * No namespaces. You can add translations while runtime without the need for namespaces If you want some kind of namespaces you can use multidimensional objects * No nesting. Could be implemented with a plugin * No objects, no arrays * No formatting. Could be implemented with a plugin ### Extendability (Plugins) There will be a few plugins on stable release. Planed are: * **[done]** Datetime Formatter, like `[[date|1558819424|short]]` to `05/25` * **[done]** Currency Formatter, like `[[cur|2.323122]]` to `€ 2,32` * **[done]** Number Formatter, like `[[number|2.323122|2]]` to `2,32` * **[todo]** Html2Char Converter, for some useful codes like `­` to `0x00AD` The reason why this functionality isn't included in the main bundle is that in many cases they are not needed, or you need only one or two and not all. ### Usage ##### Step 1 - Creating an instance of the Translator ```typescript import {Translator} from "@owja/i18n"; const translator = new Translator({default:"de",fallback:"en"}); ``` If you use a [dependency injection tool](https://github.com/owja/ioc), you can bind the `.t()` method of the `translator` constant to make accessing the main functionality as easy as possible. ##### Step 2 - Importing Translations a) Adding with static imports ```typescript import de from "lang/de.json"; import en from "lang/de.json"; translator.addResource("de", de); translator.addResource("en", en); ``` b) Adding with dynamic imports ```typescript import("lang/de.json").then((m) => translator.addResource("de", m.default)); import("lang/en.json").then((m) => translator.addResource("en", m.default)); ``` c) Adding with fetch ```typescript fetch("lang/de.json").then(r => r.json()) .then((r) => translator.addResource("de", r)); fetch("lang/en.json").then(r => r.json()) .then((r) => translator.addResource("en", r)); ``` ##### Step 3 - Translate something *lang/de.json* ```json { "hello": "Hallo Welt", "car": "Auto", "car_other": "Autos", "employee_male_0": "Kein Mitarbeiter", "employee_male_one": "Der Mitarbeiter", "employee_male_other": "Die Mitarbeiter", "employee_female_0": "Keine Mitarbeiterinnen", "employee_female_one": "Die Mitarbeiterin", "employee_female_other": "Die Mitarbeiterinnen", "dashboard": { "button": "Ok" }, "contact": { "button": "Senden" } } ``` ```typescript translate.t("hello"); // output: "Hallo Welt" translate.t("car", {count: 2}); // output: "Autos" translate.t("car", {count: 1}); // output: "Auto" translate.t("employee", {count: 0, context: "male"}); // output: "Kein Mitarbeiter" translate.t("employee", {count: 1, context: "male"}); // output: "Der Mitarbeiter" translate.t("employee", {count: 2, context: "male"}); // output: "Die Mitarbeiter" translate.t("employee", {count: 0, context: "female"}); // output: "Keine Mitarbeiterinnen" translate.t("employee", {count: 1, context: "female"}); // output: "Die Mitarbeiterin" translate.t("employee", {count: 2, context: "female"}); // output: "Die Mitarbeiterinnen" translate.t("dashboard.button"}); // output: "Ok" translate.t("contact.button"}); // output: "Senden" ``` `Intl.PluralRules` is used under the hood to get the rule for the current set locale. For example this is in german and english: * **-1** is `one` * **1** is `one` * **everything else** is `other` ...and in arabic: * **less than -10** is `many` * **-3 to -10** is `few` * **-2** is `two` * **-1** is `one` * **0** is `zero` * **1** is `one` * **2** is `two` * **3 to 10** is `few` * **greater than 10** is `many` ##### Setting the Language and Listening Setting the language: ```typescript translate.locale("de"); // sets only the language and is guessing the region which will result in DE in this case translate.locale("de-DE"); // sets language and region translate.locale(new Intl.Locale("de-DE")); // sets language and region too translate.locale("zh-Hant-HK"); // sets language, script and region translate.locale(new Intl.Locale("zh-Hant-HK")); // sets language, script and region too ``` Getting the language: ```typescript translate.short(); // short locale (language) like "en" or like "zh-Hant" if script was set translate.long(); // long locale like "en-GB" or like "zh-Hant-HK" if script was set translate.script(); // long script like "Hant" if script was set else it returns undefined translate.region(); // region of the current locale like "DE" if "de" or "de-DE" was set ``` Listening to language change and unsubscribe: ```typescript // subscribe const unsubscribe = translate.listen(() => alert("language was changed")); // and this will unsubscribe the listener unsubscribe(); ``` > Note: The callback will get triggered on some other changes too, like new translation resources or plugins got added. ### Inspiration This library is made with inspiration of the well known [i18next](https://github.com/i18next/i18next) framework. ### License **MIT** Copyright © 2019 - 2020 Hauke Broer