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
IntlAPIs.[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"andtranslations.ja.home.title = "ようこそ".[1]
- Example:
- A current locale state, usually stored in memory plus
localStorageso 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]
- 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]
- 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]
- 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]
- Wire it into your UI
- In plain HTML, you can use a
data-i18nattribute and a small translator that walks the DOM and replaces content.[6] - In React, you can wrap
tin 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
i18nextandreact-i18next. - Store translations in JSON files like
/public/locales/en/common.json. - Initialize i18next in a shared
i18n.ts/i18n.jsfile and then use theuseTranslationhook 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...