Skip to content

ripenko/localizationservice

Repository files navigation

localizationservice

The simple localization service

Also there is localizationkeys-webpack that generates typescript class of localization keys. See [https://github.com/ripenko/localizationkeys-webpack].

Installation

npm install --save localizationservice

Usage

Simple usage

method localize

import LocalizationService from "localizationservice";

const defaultLanguage = {
  Key1: "Value 1",
  Key2: {
    Key21: "Value 21",
  },
};

const service = new LocalizationService({
  importedLanguages: {
    [LocalizationService.DEFAULT_CULTURE_NAME]: defaultLanguage,
  },
  currentLanguage: defaultLanguage,
});

const localized: string = service.localize("Key2.Key21");
console.log(localized); // "Value 21"

Example. The facade pattern with event bus integration

The events bus is eventservice. See [https://github.com/ripenko/eventservice]

There are two localization files default.jsonc and de-de.json. To generate localization keys from default.jsonc file we can use webpack plugin [https://github.com/ripenko/localizationkeys-webpack].

The Localization.ts file in your app.

import LocalizationService from "localizationservice";
import EventService from "eventservice";

export default class Localization {
  private static service: LocalizationService | null = null;

  public static localize<T = string>(key: string, ...formatArgs: string[]): T {
    if (Localization.service == null) initService();
    return Localization.service.localize(key, formatArgs);
  }

  private static initService(): void {
    const defaultLanguage = require("localization/default.jsonc");
    const germanLanguage = require("localization/de-de.jsonc");
    Localization.service = new LocalizationService({
      importedLanguages: {
        [LocalizationService.DEFAULT_CULTURE_NAME]: defaultLanguage,
        "de-de": germanLanguage,
      },
      onLanguageChanged: (
        languageName: string,
        language: ILocalizationLanguage
      ): Promise<void> => {
        // we can notify subscribers that the current language has been changed.
        // if we use momentjs then we can change locale by `moment.locale(languageName);`
        // or numeraljs, etc...
        return EventService.fire("Events.Localization.LanguageChanged", {
          name: languageName,
          langauge: language,
        });
      },
      onLanguageImported: (
        languageName: string,
        language: ILocalizationLanguage
      ): Promise<void> => {
        // we can load language from api or some another place async to import it by `service.importLanguage` method
        // when new language will be imported we can update UI by refreshing a list of available languages
        return EventService.fire("Events.Localization.LanguageImported", {
          name: languageName,
          langauge: language,
        });
      },
      onLocalizationMissing: (
        key: string,
        _languageName: string,
        _language: ILocalizationLanguage | null,
        _formatArgs: string[]
      ): string => {
        // When localization has been not found in current language we return just key.
        // The testers could find easy such unlocalizated places.
        // Or we can notify insights about missing values.
        // Or we can try to get value from default language.
        // Or write in the console, etc...
        return key;
      },
    });
  }
}

Return localized object instead of certain string

Method localize. By default return type of method localize<T = string> is string. If we pass a localization key that point doesn't point to string, but it points to the parent nested object, then localized result will be object. Typically usecases:

  • dynamic key. if localization key is computed
  • localized object should be passed to some component. (Example: Globalization, or localization of some Telerik control)
import LocalizationService from "localizationservice";

interface IFeatureString {
  Title: string;
  Description: string;
}

const defaultLanguage = {
  Feature: {
    Title: "Some Title",
    Description: "Some Description",
  },
};

const service = new LocalizationService({
  importedLanguages: {
    [LocalizationService.DEFAULT_CULTURE_NAME]: defaultLanguage,
  },
  currentLanguage: defaultLanguage,
});

const result: IFeatureString = service.localize<IFeatureString>("Feature");
console.log(result); // -> { Title: "Some Title", Description: "Some Description" }

Changing the current language

method changeLanguage

import LocalizationService from "localizationservice";

const defaultLanguage = {
  Key1: "Value 1",
  Key2: {
    Key21: "Value 21",
  },
};

const germanLanguage = {
  Key1: "Wert 1",
  Key2: {
    Key21: "Wert 21",
  },
};

const service = new LocalizationService({
  importedLanguages: {
    [LocalizationService.DEFAULT_CULTURE_NAME]: defaultLanguage,
    "de-de": germanLanguage,
  },
  currentLanguage: defaultLanguage,
});

await service.changeLanguage("de-DE"); // language name case will be lowered => de-de

const localized: string = service.localize("Key2.Key21");
console.log(localized); // "Wert 21"

Using onChangeLanguage handler. When the current language has been changed

method changeLanguage and constructor options property onChangeLanguage.

import LocalizationService from "localizationservice";

const defaultLanguage = {
  Key1: "Value 1",
  Key2: {
    Key21: "Value 21",
  },
};

const germanLanguage = {
  Key1: "Wert 1",
  Key2: {
    Key21: "Wert 21",
  },
};

const service = new LocalizationService({
  importedLanguages: {
    [LocalizationService.DEFAULT_CULTURE_NAME]: defaultLanguage,
    "de-de": germanLanguage,
  },
  currentLanguage: defaultLanguage,
  onChangeLanguage: async (
    languageName: string,
    language: ILocalizationLanguage | null
  ): Promise<void> => {
    console.info(languageName, language);
  },
});

await service.changeLanguage("de-DE"); // language name case will be lowered => de-de
// -> de-de { Key1: "Wert 1", Key2: { Key21: "Wert 21" } }

Importing new language using language property __cultureName__

method importLanguage.

import LocalizationService from "localizationservice";

const defaultLanguage = {
  Key1: "Value 1",
  Key2: {
    Key21: "Value 21",
  },
};

const germanLanguage = {
  __cultureName__: "de-de",
  Key1: "Wert 1",
  Key2: {
    Key21: "Wert 21",
  },
};

const service = new LocalizationService({
  importedLanguages: {
    [LocalizationService.DEFAULT_CULTURE_NAME]: defaultLanguage,
  },
  currentLanguage: defaultLanguage,
});

// `__cultureName__` of `germanLanguage` will be used to definde language name
// The method doesn't change the current language. See `changeLanguage`.
// The language name detection priority is language property `__cultureName__`,
// if there is no, then parameter `name`. If the parameter `name` is undefined,
// then `LocalizationService.DEFAULT_CULTURE_NAME`
await service.importLanguage(germanLanguage);

const localized: string = service.localize("Key2.Key21");
console.log(localized); // "Value 21"

Importing new language using optional method parameter name

method importLanguage.

import LocalizationService from "localizationservice";

const defaultLanguage = {
  Key1: "Value 1",
  Key2: {
    Key21: "Value 21",
  },
};

const germanLanguage = {
  Key1: "Wert 1",
  Key2: {
    Key21: "Wert 21",
  },
};

const service = new LocalizationService({
  importedLanguages: {
    [LocalizationService.DEFAULT_CULTURE_NAME]: defaultLanguage,
  },
  currentLanguage: defaultLanguage,
});

// There is no `__cultureName__` of `germanLanguage`,
// then parameter `name` will be used to definde language name `de-de` (case will be lowered).
// The method doesn't change the current language. See `changeLanguage`.
await service.importLanguage(germanLanguage, "de-DE");

const localized: string = service.localize("Key2.Key21");
console.log(localized); // "Value 21"

Importing new default language

method importLanguage.

import LocalizationService from "localizationservice";

const defaultLanguage = {
  Key1: "Value 1",
  Key2: {
    Key21: "Value 21",
  },
};

const germanLanguage = {
  Key1: "Wert 1",
  Key2: {
    Key21: "Wert 21",
  },
};

const service = new LocalizationService({
  importedLanguages: {
    [LocalizationService.DEFAULT_CULTURE_NAME]: defaultLanguage,
  },
  currentLanguage: defaultLanguage,
});

// `__cultureName__` of `germanLanguage` will be used to definde language name
// The method doesn't change the current language. See `changeLanguage`.
await service.importLanguage(germanLanguage);

// To apply updated language you have to refresh current language
await service.changeLanguage();

const localized: string = service.localize("Key2.Key21");
console.log(localized); // "Wert 21"

Using on onLanguageImported handler. When the language has been imported.

constructor option onLanguageImported or property onLanguageImported.

import LocalizationService from "localizationservice";

const defaultLanguage = {
  Key1: "Value 1",
  Key2: {
    Key21: "Value 21",
  },
};

const service = new LocalizationService({
  onLanguageImported: async (
    name: string,
    language: ILocalizationLanguage
  ): Promise<void> => {
    console.log(name, language);
  },
});

// `__cultureName__` of `defaultLanguage` will be used to definde language name
// The method doesn't change the current language. See `changeLanguage`.
await service.importLanguage(defaultLanguage);
// -> "" { Key1: "Value 1", Key2: { Key21: "Value 21" } }

Using on onLocalizationMissing handler. When localization string has been not found

constructor option onLocalizationMissing or property onLocalizationMissing.

import LocalizationService from "localizationservice";

const service = new LocalizationService({
  // name will be `LocalizationService.DEFAULT_CULTURE_NAME`, language is `{}`
  onLocalizationMissing: (
    key: string,
    name: string,
    language: ILocalizationLanguage
  ): string => {
    return `Missed '${key}' for default language`;
  },
});

const result: string = service.localize("SomeKey");
console.log(result); // -> "Missed 'SomeKey' for default language"

Credits

Alexey Ripenko, GitHub

License

MIT

About

The simple localization service

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published