Frontend I18n

Table of Contents

Locale Sources

Backend config.locale remains the full-stack locale foundation. frontend.i18n controls frontend page copy and hydration behavior.

The server should decide the request locale from sources such as:

  • URL prefix
  • cookie
  • user preference
  • Accept-Language
  • explicit route logic

Then res.render() sends the resolved locale and messages into the SSR document.

Frontend Locale Files

Put page copy under src/frontend/locales/**.

// src/frontend/locales/en-US.ts
export default {
  dashboard: {
    title: "Dashboard",
    welcome: "Welcome back",
  },
};
// src/frontend/locales/zh-CN.ts
export default {
  dashboard: {
    title: "仪表盘",
    welcome: "欢迎回来",
  },
};

All locale files should keep the same object shape. Missing keys should be treated as a content error.

Use Messages in Components

Vext's default frontend API is object access, not t("a.b.c").

import { useVextI18n } from "vextjs/frontend";

export default function DashboardPage() {
  const i18n = useVextI18n();
  return <h1>{i18n.dashboard.title}</h1>;
}

You can request a specific locale when the component already knows it:

const english = useVextI18n("en-US");

SSR and Hydration

The default mode is:

frontend: {
  i18n: {
    clientLoad: "current",
  },
}

"current" means the browser loads only the SSR locale for hydration. This keeps the first JS payload smaller.

Use "all" only when the page needs no-reload language switching:

frontend: {
  i18n: {
    clientLoad: "all",
  },
}

Switch Language

The simplest switching flow is reload-based:

  1. User chooses a language.
  2. Store it in a cookie, user preference API, URL prefix, or another server-visible location.
  3. Navigate or reload the page.
  4. SSR and hydration use the same locale.

Avoid making the server render one locale while the browser immediately renders another during hydration.

Cache and Vary

If HTML can vary by language, cache keys must include language.

Common strategies:

  • keep Vary: Accept-Language
  • include locale in CDN key
  • use locale path prefixes such as /en and /zh
  • include language preference cookie in the reverse-proxy key

JS/CSS files are content-hashed and do not need language-specific cache keys unless you intentionally build separate locale bundles.