@adguard/translate

Simple internationalization library with React integration

Usage no npm install needed!

<script type="module">
  import adguardTranslate from 'https://cdn.skypack.dev/@adguard/translate';
</script>

README

AdGuard Translate

Simple internationalization library with React integration

Installation

npm

npm install @adguard/translate

Yarn

yarn add @adguard/translate

Usage

Messages format

Library supports messages with placeholders, tags and plural forms

Placeholders

Placeholders should be wrapped in % mark

e.g.

"agreement_consent": {
    "message": "Servers number %count%",
}

Tags support

Library supports open/close tags, and their values should be provided in the translate method

e.g.

<a>link</a> to the text

and void tags

e.g.

<img src="server.jpg" >
Default list of tags

Next tags are not required in the translate, because they are provided by default

    <b>, <p>, <strong>, <tt>, <s>, <i>,

Plural strings

Library supports plural strings translation.

e.g.

Нет серверов | %count% сервер | %count% сервера | %count% серверов

Plural strings should follow simple rules.

  1. Plural forms should be divided by |.
  2. Plural forms count should correspond to the language plural forms count (table) + 1 (zero form).
  3. If first plural form is omitted, for the zero form you'll get empty string
| %count% сервер | %count% сервера | %count% серверов

translate

// import library
import { translate } from '@adguard/translate'

// create i18n object which implements I18nInterface:
interface I18nInterface {
    /**
     * Returns message by key for current locale
     * @param key
     */
    getMessage(key: string): string;

    /**
     * Returns current locale code
     * Locale codes should be in the list of Locales
     */
    getUILanguage(): Locales;

    /**
     * Returns base locale message
     * @param key
     */
    getBaseMessage(key: string): string;

    /**
     * Returns base locale code
     */
    getBaseUILanguage(): Locales;
}

// in the browser extension it will be "browser.i18n"

// create translate function
const translator = translate.createTranslator(i18n)

// e.g.
//  string to translate:
//  "agreement_consent": {
//      "message": "You agree to our <eula>EULA</eula>",
//  }

createTranslator

This method can be used to translate simple strings and Vue template strings

const translator = translate.createTranslator(browser.i18n);
const translatedString = translator.getMessage('agreement_consent', {
    eula: (chunks) => `<button class="privacy-link">${chunks}</button>`,
});

console.log(translatedString); // <button class="privacy-link">EULA</button>

createReactTranslator

const reactTranslator = translate.createReactTranslator(browser.i18n, React);

<div>
    {reactTranslator.getMessage('agreement_consent', {
        eula: (chunks) => (
            <button
                className="auth__term"
                onClick={handleEulaClick}
            >
                {chunks}
            </button>
        ),
    })}
</div>

validator

// import library
import { validator } from '@adguard/translate'

isTranslationValid

const baseMessage = 'test string <a>has node</a>';
const targetMessage = 'тестовая строка <a>с нодой</a>';

validator.isTranslationValid(baseMessage, targetMessage); // true

isPluralFormValid

validator.isPluralFormValid(%count% серверов | %count% сервер | %count% сервера | %count% серверов, 'ru', "servers_count"); // true, all 4 plural forms are provided

validator.isPluralFormValid(%count% сервера | %count% серверов, 'ru', "servers_count"); // false, ru locale awaits for 4 plural forms provided

API

createTranslator

/**
 * Creates translator instance strings, by default for simple strings
 * @param i18n - function which returns translated message by key
 * @param messageConstructor - function that will collect messages
 * @param values - map with default values for tag converters
 */
const createTranslator = (
    i18n: I18nInterface,
    messageConstructor?: MessageConstructorInterface,
    values?: ValuesAny
): Translator

createReactTranslator

/**
 * Creates translation function for strings used in the React components
 * We do not import React directly, because translator module can be used
 * in the modules without React too
 *
 *
 * @param i18n - object with methods which get translated message by key and return current locale
 * @param React - instance of react library
 */
  const createReactTranslator = (i18n: I18nInterface, React: ReactCustom): Translator

getMessage

/**
 * Retrieves message and translates it, substituting parameters where necessary
 * @param key - translation message key
 * @param params - values used to substitute placeholders and tags
 */
public getMessage(key: string, params: ValuesAny = {}): T {

getPlural

/**
 * Retrieves correct plural form and translates it
 * @param key - translation message key
 * @param number - plural form number
 * @param params - values used to substitute placeholders or tags if necessary,
 * if params has "count" property it will be overridden by number (plural form number)
 */
public getPlural(key: string, number: number, params: ValuesAny = {}): T {

isTranslationValid

/**
 * Validates translation against base string by AST (abstract syntax tree) structure
 * @param baseMessage - base message
 * @param translatedMessage - translated message
 */
const isTranslationValid = (baseMessage: string, translatedMessage: string): boolean

isPluralFormValid

/**
 * Checks if plural forms are valid
 * @param str - message string
 * @param locale - message locale
 * @param key - message key, used for clearer log message
 */
const isPluralFormValid = (str: string, locale: Locales, key: string): boolean => {

Development

Use yarn to build the library

Build

To build the library run:

yarn build

Build result would be in the dist directory

Lint

To check lint errors run in terminal:

yarn lint

Test

The library uses jest for running unit-tests. To launch the tests, run the following command in the terminal:

yarn test

Docs

To build documentation, run the following command in the terminal:

yarn docs

TODO

  • Create Vue plugin
  • Add utility to check if code contains unused or redundant translation messages

License

MIT