Why i18n matters from day one

Why i18n matters from day one

Internationalization is the foundation that lets you localize content (text, dates, currencies) for different regions without rewriting your UI.[2][3] For a product like Everflow, adding i18n early means you can ship the same core experience to New York, Tokyo, or Berlin just by swapping translation data instead of forking the codebase.[4][2]

  • It decouples copy from code so designers and translators can work without touching logic.[2]
  • It enforces consistent handling of locale-sensitive pieces like dates, numbers, and currencies using the JavaScript Intl APIs.[3]
  • It keeps you flexible when marketing or compliance suddenly requires “just one more language” on short notice.[5][4]

The minimal building blocks

Even without any library, most simple i18n setups boil down to four core pieces.[6][1]

  • A translations object keyed by language and string key
    • Example: translations.en.home.title = "Welcome" and translations.ja.home.title = "ようこそ".[1]
  • A current locale state, usually stored in memory plus localStorage so the user’s preference persists across sessions.[7][1]
  • A small t(key, params?) function that returns the translated string and optionally interpolates variables like {name}.[1]
  • A way to bind those translations to your UI (data attributes in plain JS, hooks/components in React, or template helpers in other frameworks).[8][6]

With this structure in place, adding a new language is just adding another language block to the translations object and updating your language switcher.[2][1]

A simple i18n implementation in JavaScript

Below is a minimal pattern that works in plain JavaScript and translates cleanly into React, Vue, or a server-rendered setup.[6][1]

  1. Define your translations
const translations = { en: { hero: { title: "Build global-ready products", subtitle: "Everflow helps you ship multilingual experiences from day one." } }, ja: { hero: { title: "グローバル対応プロダクトを構築", subtitle: "Everflow は最初から多言語対応の体験を提供します。" } } };

This nested structure lets you reference copy via stable keys like hero.title instead of hard-coded strings scattered in components.[1]

  1. Keep track of the current locale
let currentLocale = localStorage.getItem("locale") || "en"; function setLocale(locale) { currentLocale = locale; localStorage.setItem("locale", locale); rerender(); // your framework-specific way to refresh UI }

Using localStorage makes your locale choice sticky so returning users see the same language they picked previously.[7]

  1. Create a tiny translation helper
function getNested(obj, path) { return path.split(".").reduce((acc, part) => acc && acc[part], obj); } function t(key, vars = {}) { const raw = getNested(translations[currentLocale], key) || getNested(translations.en, key) || // fallback key; return raw.replace(/{([^{}]*)}/g, (match, name) => { const value = vars[name]; return typeof value === "string" || typeof value === "number" ? value : match; }); }

This mirrors popular lightweight approaches: it supports nested keys ("hero.title") and simple string interpolation like t("hero.greeting", { name: "Aki" }).[1]

  1. Wire it into your UI
  • In plain HTML, you can use a data-i18n attribute and a small translator that walks the DOM and replaces content.[6]
  • In React, you can wrap t in a hook and use it directly in JSX:
function Hero() { return ( <section> <h1>{t("hero.title")}</h1> <p>{t("hero.subtitle")}</p> </section> ); }

This keeps your components declarative while still using a very small i18n core.[9][10]

When to move to a full i18n stack

The minimal pattern above works well for early-stage products, marketing sites, and small dashboards, but it has limits as your product and translation team grow.[4][2]

You should consider a specialized library like i18next or React-Intl when:[11][12][13]

  • You need pluralization rules, gendered phrases, or language-specific formatting logic.
  • You want asynchronous loading of translation bundles per route or per feature to keep performance tight.[14][11]
  • You integrate with platforms like Localazy, Lokalise, or Crowdin to manage translation workflows and automate syncing.[8][9][2]

For React apps, a common next step is:

  • Install i18next and react-i18next.
  • Store translations in JSON files like /public/locales/en/common.json.
  • Initialize i18next in a shared i18n.ts/i18n.js file and then use the useTranslation hook everywhere in your components.[10][9][14][8]

This lets Everflow projects start simple and graduate smoothly into an enterprise-grade i18n pipeline when the product and audience demand it.[12][11][4]

Comments

Loading comments...