Skip to content

Repository files navigation

@e22m4u/js-localizer

npm version license

Легковесный сервис локализации для JavaScript.

  • Перевод по ключу словаря методом t(key, ...args)
  • Перевод по языковому объекту методом o(langObject, ...args)
  • Вложенные словари с доступом через dot-нотацию
  • Автоматическое склонение чисел через нативный Intl.PluralRules
  • Форматирование строк (%s, %d, %v и др.) через @e22m4u/js-format
  • Автоматический фолбэк на резервную локаль и остальные словари
  • Опция noEmptyString для игнорирования пустых строк как перевода
  • Получение списка доступных локалей методом getAvailableLocales()
  • Динамическая установка и замена словарей методом setDictionary()
  • Поддержка TypeScript (файлы .d.ts включены в сборку)

Содержание

Установка

npm install @e22m4u/js-localizer

Модуль поддерживает ESM и CommonJS стандарты.

ESM

import {Localizer} from '@e22m4u/js-localizer';

CommonJS

const {Localizer} = require('@e22m4u/js-localizer');

Использование

Создание экземпляра с указанием словарей и выполнение перевода.

import {Localizer} from '@e22m4u/js-localizer';

// создание экземпляра с указанием словарей
const localizer = new Localizer({
  locale: 'ru',         // текущая локаль (опционально, по умолчанию резервная)
  fallbackLocale: 'en', // резервная локаль (опционально, по умолчанию "en")
  dictionaries: {       // словари переводов (опционально)
    en: {
      hello: 'Hello!',
      helloName: 'Hello, %s!',
    },
    ru: {
      hello: 'Привет!',
      helloName: 'Привет, %s!',
    },
  },
});

// перевод по словарю используя ключ
console.log(localizer.t('hello'));             // > Привет!
console.log(localizer.t('helloName', 'Олег')); // > Привет, Олег!

// перевод по языковому объекту (без словарей)
// (внимание, используется метод `o` вместо `t`)
console.log(localizer.o({en: 'Hello!', ru: 'Привет!'})); // > Привет!

// изменение текущей локали
localizer.setLocale('en');

console.log(localizer.t('hello'));             // > Hello!
console.log(localizer.t('helloName', 'John')); // > Hello, John!

console.log(localizer.o({en: 'Hello!', ru: 'Привет!'})); // > Hello!

i. Форматирование строк (%s, %d и др.) выполняется с помощью модуля @e22m4u/js-format.

Вложенные словари

Сервис локализации поддерживает использование вложенных объектов в словарях. Доступ к вложенным значениям выполняется с помощью dot-нотации.

Пример структуры словаря:

// в данном примере используется метод `setDictionary`,
// который устанавливает новый справочник
// (или переопределяет существующий)
localizer.setDictionary('ru', {
  group: {
    title: 'Заголовок',
    validation: {
      required: 'Обязательное поле'
    }
  }
});

localizer.setLocale('ru');

console.log(localizer.t('group.title')); // Заголовок
console.log(localizer.t('group.validation.required')); // Обязательное поле

При поиске перевода приоритет отдается плоским ключам. Если в словаре присутствует ключ с точкой в названии, то обход вложенных объектов для данного пути не производится.

Пример приоритета ключей:

localizer.setDictionary('ru', {
  'group.title': 'Плоский ключ',
  group: {
    title: 'Вложенный ключ',
  },
});

console.log(localizer.t('group.title')); // Плоский ключ

Формы множественного числа

Модуль использует встроенный нативный интерфейс Intl.PluralRules для определения правильной формы множественного числа. Склонения указываются в объекте со специальными ключами, список которых зависит от выбранной локали.

Пример для английского языка (2 формы)

Для языков с двумя формами множественного числа (например, английского) достаточно указать $one и $other. Библиотека автоматически использует вторую форму для всех чисел, кроме 1 и -1.

localizer.setDictionary('en', {
  iHaveApples: {
    $one: 'I have an apple',
    $other: 'I have %d apples',
  },
});

localizer.setLocale('en');

console.log(localizer.t('iHaveApples', 1));   // > I have an apple
console.log(localizer.t('iHaveApples', 0));   // > I have 0 apples
console.log(localizer.t('iHaveApples', 10));  // > I have 10 apples

Пример для русского языка (3 формы)

Для языков с тремя формами множественного числа (например, русского) необходимо указать три ключа ($one, $few и $many). Библиотека автоматически выбирает нужную форму в зависимости от числа.

localizer.setDictionary('ru', {
  iHaveApples: {
    $one: 'У меня одно яблоко',
    $few: 'У меня %d яблока',  // для чисел 2, 3, 4 и т.п.
    $many: 'У меня %d яблок',  // для 0, 5, 6...
    $other: 'У меня %d яблока' // для дробных чисел (опционально)
  },
});

localizer.setLocale('ru');

console.log(localizer.t('iHaveApples', 1)); // > У меня одно яблоко
console.log(localizer.t('iHaveApples', 3)); // > У меня 3 яблока
console.log(localizer.t('iHaveApples', 5)); // > У меня 5 яблок

Пример для арабского языка (6 форм)

Для языков с шестью формами множественного числа (например, арабского) используется полный набор ключей ($zero, $one, $two, $few, $many и $other). Выбор подходящей формы осуществляется автоматически в зависимости от переданного числа.

localizer.setDictionary('ar', {
  iHaveApples: {
    $zero: '٠ تفاحة',    // для 0
    $one: 'تفاحة واحدة', // для 1
    $two: 'تفاحتان',     // для 2
    $few: '%d تفاحات',   // для 3-10
    $many: '%d تفاحة',   // для 11-99
    $other: '%d تفاحة'   // для 100 и более, а также для дробей
  },
});

localizer.setLocale('ar');

console.log(localizer.t('iHaveApples', 0));   // > ٠ تفاحة
console.log(localizer.t('iHaveApples', 1));   // > تفاحة واحدة
console.log(localizer.t('iHaveApples', 2));   // > تفاحتان
console.log(localizer.t('iHaveApples', 5));   // > 5 تفاحات
console.log(localizer.t('iHaveApples', 15));  // > 15 تفاحة
console.log(localizer.t('iHaveApples', 100)); // > 100 تفاحة

Трюк с несколькими аргументами

Если в строке перевода используется несколько параметров (например, ID пользователя в виде строки и количество), библиотека автоматически найдет первый аргумент типа number для определения нужной формы. Строковые аргументы (даже если они состоят только из цифр) безопасно игнорируются при выборе склонения.

// строка "1" подставится вместо %s и проигнорируется при выборе склонения,
// число 5 подставится вместо %d и определит форму множественного числа
console.log(localizer.o({
  en: {
    $one: 'User %s has one apple',
    $other: 'User %s has %d apples'
  }
}, '1', 5));
// > User 1 has 5 apples

Таким образом число 1 скрывается от логики определения числовой формы, так как передается в виде строки. Локализатор реагирует только на первый аргумент с числовым типом данных, которым в данном случае является число 5.

Перевод по языковому объекту

Метод o() удобен, когда переводы хранятся не в глобальных словарях, а непосредственно в коде (например, в UI-компоненте).

const localizer = new Localizer({locale: 'ru'});

const title = {
  en: 'Hello!',
  ru: 'Привет!',
};

console.log(localizer.o(title)); // > Привет!

// метод также поддерживает склонения
const counter = {
  en: {$one: '%d item', $other: '%d items'},
  ru: {$one: '%d товар', $few: '%d товара', $many: '%d товаров'},
};

console.log(localizer.o(counter, 5)); // > 5 товаров

// тот же пример для другой локали
localizer.setLocale('en');

console.log(localizer.o(title));      // > Hello!
console.log(localizer.o(counter, 5)); // > 5 items

Если перевод для текущей локали отсутствует, будет использована резервная локаль, а если и она недоступна, то будет возвращён перевод для первого найденного языка в объекте. Если подходящий перевод так и не будет найден (например, объект пуст), то метод вернёт пустую строку.

Настройки конструктора

Параметры передаются в конструктор new Localizer(options).

  • locale?: string
    Текущая локаль. Используется как основная локаль для поиска соответствующего словаря или перевода в языковом объекте.
    По умолчанию: undefined

  • fallbackLocale?: string
    Резервная локаль. Используется, если перевод для текущей локали не найден или текущая локаль не определена.
    По умолчанию: 'en'

  • dictionaries?: LocalizerDictionaries
    Объект со словарями, где ключ является локалью.
    По умолчанию: {}

  • noEmptyString?: boolean
    Запрещает использование пустых строк в качестве переводов. Если включено, а перевод представляет собой пустую строку, локализатор проигнорирует её и попытается найти перевод в резервной локали.
    По умолчанию: false

Методы экземпляра

  • getLocale(): string
    Возвращает текущую локаль. Если текущая локаль не установлена, то возвращается резервная локаль.

  • setLocale(locale: string): this
    Устанавливает текущую локаль. Это значение будет иметь приоритет над резервной локалью.

  • getFallbackLocale(): string
    Возвращает резервную (альтернативную) локаль. По умолчанию "en".

  • setFallbackLocale(locale: string): this
    Устанавливает резервную локаль. Локаль будет использоваться для поиска перевода, если текущая локаль не задана, либо если в словаре текущей локали отсутствует нужный ключ.

  • getAvailableLocales(): string[]
    Возвращает локали имеющихся справочников.

  • setDictionary(locale: string, dictionary: object): this
    Устанавливает или заменяет словарь для указанной локали.

  • t(key: string, ...args: unknown[]): string
    Возвращает переведённую и отформатированную строку по ключу из словаря.

  • o(obj: object, ...args: unknown[]): string
    Извлекает и форматирует перевод из переданного объекта для текущей локали.

Тесты

npm test

Лицензия

MIT

About

Легковесный сервис локализации для JavaScript

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages