Skip to content

Internationalization (i18n)

Brandon Scott edited this page Feb 10, 2021 · 3 revisions

Documentation for configuring a project to leverage the various internationalization (i18n) / localization (l10n) tools.

At its core, our i18n utilities are driven by the popular i18next javascript library. The hope is through use of our various actors and utilities, configuration is greatly simplified for javascript applications.

Adding languages / cultures

We like typescript at andculture, so we've setup our utilities to benefit from typings. Before we can even initialize the application, we must have some languages/cultures created.

The andculture core package provides various typed version of languages (ie. BaseEnglishUnitedStates, BaseSpanishSpain). Using the LocalizationUtils.cultureFactory you can create an application versions.

First define your translation keys with an interface

// interfaces/CultureResources.ts

interface CultureResources {
    createAnAccount: string;
    signIn: string;
}

export { CultureResources };

Create your application culture files

// cultures/english-united-states.ts

import {
    BaseEnglishUnitedStates,
    Culture,
    LocalizationUtils,
} from "andculturecode-javascript-core";
import CultureResources from "interfaces/culture-resources";

const EnglishUnitedStates: Culture<CultureResources> = LocalizationUtils.cultureFactory(
    BaseEnglishUnitedStates,
    {
        resources: {
            createAnAccount: "Create An Account",
            signIn: "Sign In",
        },
    }
);

export default EnglishUnitedStates;
// cultures/spanish-spain.ts

import {
    BaseEnglishUnitedStates,
    Culture,
    LocalizationUtils,
} from "andculturecode-javascript-core";
import CultureResources from "interfaces/culture-resources";

const SpanishSpain: Culture<CultureResources> = LocalizationUtils.cultureFactory(
    BaseSpanishSpain,
    {
        resources: {
            createAnAccount: "Crea una cuenta",
            signIn: "Registrarse",
        },
    }
);

export default SpanishSpain;

Initialization

During startup of your application, an initialization is required before other code call request translations, change language, or so forth.

With your newly created culture files created, initialize your application.

// app.tsx

import CultureResources from "interfaces/culture-resources";
import { LocalizationUtils } from "andculturecode-javascript-core";
import EnglishUnitedStates from "cultures/english-united-states";
import SpanishSpain from "cultures/spanish-spain";

const module = {}; // ie. in react it would be initReactI18next

LocalizationUtils.initialize<CultureResources>(module, [
    EnglishUnitedStates,
    SpanishSpain,
]);

Detect language

With the application initialized with your cultures, setup your application to detect and initialize the requested culture/language.

// app.tsx

const cultureCode = LocalizationUtils.detectCultureCode();
ServiceUtils.configureCultureCode(cultureCode);

Translate your application!

Now that your application is fully configured, go ahead and swap out any hard-coded strings with translation functions

// views/my-view.tsx

import { LocalizationUtils } from "andculturecode-javascript-core";

...

<h1>{LocalizationUtils.t("createAnAccount")</h1>

Key naming strategy

  1. Keep them as short as possible without over-abbreviating (same as any variable naming) to ease use
  2. Avoid namespacing keys unless there is a strong argument for it (conflict with existing key that has different copy/cannot be used, etc.)
  3. Err on the side of leveraging generic keys w/ interpolation first, and let the professional translators determine which copy might need to be modified due to sentence structure/grammar
  4. Try to look in the english translation file to find similar messaging that can be reused before adding a specialized key
  5. For pluralizing words, use the _plural key suffix. You can then pass in an object with a count property during translation, and i18next will know whether to use the singular key or plural key. See i18next - Plurals
    • t("result", { count: objects.length }); will render result_plural if objects.length > 1