Docs menu

i18n

Vite/React uses i18next. Next uses next-intl. Sections below are separate — do not mix APIs.

Defaults to No. When enabled, Dose injects a stack-native setup. Use only the section that matches your project.

React + i18next

Vite SPA & React Router

Libraries: i18next + react-i18next. Locale is not in the URL. Persist via localStorage.lang.

Files injected

text
src/i18n/index.ts
src/i18n/locales/en.json
src/i18n/locales/ar.json
src/hooks/useLocale.ts
src/i18n/i18next.d.ts          # TypeScript only

What we wire

  • RootProvider <I18nextProvider i18n={i18n}>
  • Entry imports @/i18n from main.* (SPA) or root.* (Router)
  • Locales en / ar, fallback en

Helper hook — useLocale

tsxComponent.tsx
import { useLocale } from "@/hooks/useLocale";

export function LanguageSwitcher() {
  const { t, changeLanguage, currentLanguage } = useLocale();

  return (
    <div>
      <p>{t("welcome")}</p>
      <p>Current: {currentLanguage}</p>
      <button type="button" onClick={() => changeLanguage("ar")}>
        العربية
      </button>
      <button type="button" onClick={() => changeLanguage("en")}>
        English
      </button>
    </div>
  );
}

changeLanguage writes localStorage.lang then calls i18n.changeLanguage. Add keys under src/i18n/locales/*.json. You can also use useTranslation() from react-i18next.

Next + next-intl

Next.js App Router

Library: next-intl. Locales live in the URL (/en/..., /ar/...). Do not use the Vite useLocale hook here.

Files injected

text
messages/en.json
messages/ar.json
src/i18n/routing.ts
src/i18n/navigation.ts
src/i18n/request.ts
src/proxy.ts
src/app/layout.tsx
src/app/page.tsx
src/app/[locale]/layout.tsx
src/app/[locale]/page.tsx
next.config.ts

What we wire

  • [locale]/layout wraps NextIntlClientProvider via RootProvider
  • Root / redirects to /{locale}
  • html gets lang + dir (ar → RTL)
  • next.config uses createNextIntlPlugin()

Navigation — use @/i18n/navigation

tsxNavLink.tsx
import { Link, useRouter, usePathname } from "@/i18n/navigation";

export function NavLink() {
  const pathname = usePathname();
  const router = useRouter();

  return (
    <>
      <Link href="/about">About</Link>
      <button type="button" onClick={() => router.push("/contact")}>
        Contact ({pathname})
      </button>
    </>
  );
}

Prefer these helpers over next/link and next/navigation so the active locale stays in the URL.

Translations — next-intl APIs

tsxWelcome.tsx
import { useTranslations, useLocale } from "next-intl";

export function Welcome() {
  const t = useTranslations();
  const locale = useLocale();

  return (
    <p>
      {t("welcome")}{locale}
    </p>
  );
}

Add messages in messages/en.json and messages/ar.json. Server layouts use getMessages / setRequestLocale as in the generated [locale]/layout.