Skip to content

Latest commit

 

History

History
169 lines (130 loc) · 4.88 KB

translations.md

File metadata and controls

169 lines (130 loc) · 4.88 KB

Translations of addons

Addons should be multilangual if possible. For this problem we have various solutions.

Using TranslatedText

The most easy way to translate an addon is via values with the type TranslatedText. This type supports either a string of text, or a mapping of language=>text pairs.

{
  "sometext": "This is some text which is not translated",
  "othertext": {
    "en": "This is some english text",
    "de": "Das ist die deutsche Übersetzung",
    "cn": "这是一些中文文本"
  }
}

Using @watchedcom/i18n

Short after this documentation was written, I created a little helper module for i18next. Please see the documentation at packages/i18n/README.md.

Using i18next

The i18next module is an easy way to translate projects of any size.

Using the i18next-node-fs-backend storage backend

npm i --save i18next i18next-node-fs-backend

Create a file named src/i18n.ts:

import i18next from "i18next";
import FsBackend from "i18next-node-fs-backend";
import path from "path";

i18next.use(
  new FsBackend(null, {
    loadPath: path.join("locales", "{{lng}}", "{{ns}}.json"),
    addPath: path.join("locales", "{{lng}}", "{{ns}}.missing.json"),
    jsonIndent: 2
  })
);

i18next.init({
  debug: false,
  fallbackLng: "en",
  whitelist: ["en", "de"],
  ns: ["your-addon-id"],
  defaultNS: "your-addon-id",
  load: "languageOnly",
  saveMissing: true,
  updateMissing: true
});

export const i18n = i18next;

Inside your action handler, you can use this to get an instance to the t function:

import { i18n } from "./i18n";
const t = await i18n.cloneInstance().changeLanguage(input.language);
const translated = t("some.key", "Some default text");

Using the locize translation service

This example will use the i18next-node-locize-backend storage backend, and environment variables for configuration.

When this environment variables are missing, it will fall back to the i18next-node-fs-backend. This is the best way to deploy projects to for example serverless environments. For more infos regarding this, click here.

npm i --save i18next i18next-node-fs-backend i18next-node-locize-backend
npm i --save-dev locize-cli

Your src/i18n.js file:

import i18next from "i18next";
import FsBackend from "i18next-node-fs-backend";
import LocizeBackend from "i18next-node-locize-backend";
import path from "path";

if (process.env.LOCIZE_PROJECTID) {
  i18next.use(
    new LocizeBackend({
      projectId: <string>process.env.LOCIZE_PROJECTID,
      apiKey: process.env.LOCIZE_API_KEY,
      version: process.env.LOCIZE_VERSION ?? "latest"
    })
  );
} else {
  i18next.use(
    new FsBackend(null, {
      loadPath: path.join("locales", "{{lng}}", "{{ns}}.json"),
      addPath: path.join("locales", "{{lng}}", "{{ns}}.missing.json"),
      jsonIndent: 2
    })
  );
}

i18next.init({
  debug: false,
  fallbackLng: "en",
  whitelist: ["en"],
  ns: ["your-addon-id"],
  defaultNS: "your-addon-id",
  load: "languageOnly",
  saveMissing: true,
  updateMissing: true
});

export const i18n = i18next;

Modify your package.json and add the following script:

{
  "scripts": {
    "update-locize": "node -r dotenv/config node_modules/.bin/locize download --path locales --clean=true"
  }
}

Start your project with setting the environment variables for locize. After using your addon, the translations should appear inside your locize project. Add some languages, translate the strings, and download the updates:

npm run update-locize

After this you can deploy your addon without using locize. This has many benefits, especially for serverless environments.

Applying translations to an object

Imagine you want to translate the name property of this addon:

import { createWorkerAddon } from "@watchedcom/sdk";

export const myAddon = createWorkerAddon({
  id: "i18n-example",
  name: "Name of this addon"
});

We created a helper function named translateDeep for cases like this. This function works similar to the lodash.cloneDeep function, but translates all strings beginning with a specific prefix (by default i18n:) using the t parameter.

import { createWorkerAddon, translateDeep } from "@watchedcom/sdk";
import { i18n } from "./i18n";

export const myAddon = createWorkerAddon({
  id: "i18n-example",
  name: "i18n:Name of this addon"
});

myAddon.registerActionHandler("addon", async (input, ctx, addon) => {
  const t = await i18n.cloneInstance().changeLanguage(input.language);
  return translateDeep(addon.getProps(), t);
});