tagged i18n

A simple localization framework that uses tagged template literals

by sperske

HTML

<h1 id="Welcome"></h1>
<h2 id="Notice"></h2>

JavaScript

const words = {
  en: {
    "Hello ?, Welcome to ?": ["Hello ", 0, ", Welcome to ", 1],
    "You have ? songs": ["You have ", 0, " ", [0, "song", "songs"]],
  },
  es: {
    "Hello ?, Welcome to ?": ["Hola ", 0, ", Bienvenida a ", 1],
    "You have ? songs": ["tienes ", 0, " ", [0, "canción", "canciones"]],
  },
  jp: {
    "Hello ?, Welcome to ?": ["こんにちは", 0, "、", 1, "へようこそ"],
    "You have ? songs": ["あなたは", 0, "曲あります"],
  },
};

function i18n(locale, data_source) {
  if (!(locale in data_source))
    throw new Error(`locale:${locale} not available inside data_source`);
  const dictionary = data_source[locale];
  return (phrase, ...parts) => {
    const key = phrase.join("?");
    if (key in dictionary) {
      const output = [];
      try {
        for (const part of dictionary[key]) {
          if (Number.isInteger(part)) {
            output.push(parts[part]);
          } else if (Array.isArray(part)) {
            const [i, singular, plural] = part;
            output.push(parts[i] == 1 ? singular : plural);
          } else {
            output.push(part);
          }
        }
      } catch (e) {
        throw new Error(e);
      }
      return output.join("");
    } else {
      throw new Error(`key: ${key} not localized in locale:${locale}`);
    }
  };
}

const t = i18n("jp", words);
const firstName = "Jason";
const company = "SNDTST.com";
const songs = 1;

document.querySelector("#Welcome").innerText =
  t`Hello ${firstName}, Welcome to ${company}`;
document.querySelector("#Notice").innerText = t`You have ${songs} songs`;