Recipes
Idiomatic compositions across @mongez/localization features.
One file per locale (the simplest layout)
import { extend } from "@mongez/localization";
extend("en", { home: "Home", contact: "Contact Us", ui: { sidebar: "Sidebar", menu: "Menu", },});import { extend } from "@mongez/localization";
extend("ar", { home: "الرئيسية", contact: "اتصل بنا", ui: { sidebar: "الشريط الجانبي", },});import "src/locales/en";import "src/locales/ar";import { setLocalizationConfigurations } from "@mongez/localization";
setLocalizationConfigurations({ defaultLocaleCode: "en", fallback: "en",});import "src/config/localization";// rest of the appOne file per feature (keyword-first)
import { groupedTranslations } from "@mongez/localization";
groupedTranslations("cart", { empty: { en: "Your cart is empty", ar: "سلتك فارغة" }, checkout: { en: "Checkout", ar: "الدفع" }, total: { en: "Total: :amount", ar: "الإجمالي: :amount" },});Side-effect import to register them at boot:
import "./locales";export * from "./components";Typed feature dictionary with transObject
import { transObject } from "@mongez/localization";
export const t = transObject({ signIn: { en: "Sign In", ar: "تسجيل الدخول" }, signOut: { en: "Sign Out", ar: "تسجيل الخروج" }, welcomeBack: { en: "Welcome :name", ar: "مرحبا :name" },});import { t } from "./translations";
function UserMenu({ user }: { user: User }) { return ( <> <h2>{t.p("welcomeBack", { name: user.name })}</h2> <button>{t.signOut}</button> </> );}t.signOut is typed as string. t.p("welcomeBack", …) typechecks against the keys you declared.
Lazy-loading locales
import { extend, setCurrentLocaleCode } from "@mongez/localization";
const loaders: Record<string, () => Promise<Record<string, string>>> = { ar: () => import("./locales/ar.json").then(m => m.default), fr: () => import("./locales/fr.json").then(m => m.default),};
export async function switchLocale(code: string) { if (loaders[code]) { const dict = await loaders[code](); extend(code, dict); } setCurrentLocaleCode(code);}Only the locales the user actually visits are downloaded. Subsequent switches to the same locale skip the import (the bundler caches the module).
Sync the URL with the locale
import { getCurrentLocaleCode, localizationEvents, setCurrentLocaleCode,} from "@mongez/localization";
// On boot: read from URL.const url = new URL(window.location.href);const fromQuery = url.searchParams.get("lang");if (fromQuery) setCurrentLocaleCode(fromQuery);
// On switch: write back to URL.localizationEvents.onChange("localeCode", (next) => { const url = new URL(window.location.href); url.searchParams.set("lang", next); window.history.replaceState({}, "", url);});Driving React re-renders without the React adapter
import { useEffect, useState } from "react";import { getCurrentLocaleCode, localizationEvents } from "@mongez/localization";
export function useCurrentLocale() { const [locale, setLocale] = useState(getCurrentLocaleCode); useEffect(() => { const sub = localizationEvents.onChange("localeCode", (next, prev) => { if (next !== prev) setLocale(next); }); return () => sub.unsubscribe(); }, []); return locale;}function Header() { useCurrentLocale(); // subscribe; ignore the return return <h1>{trans("home")}</h1>;}Any component that calls useCurrentLocale() will re-evaluate its trans(...) calls on locale switches.
React with JSX placeholders
import { setLocalizationConfigurations } from "@mongez/localization";import { jsxConverter } from "@mongez/react-localization";
setLocalizationConfigurations({ defaultLocaleCode: "en", fallback: "en", converter: jsxConverter,});import { trans } from "@mongez/localization";
function PriceBanner() { return ( <p> {trans("minimumOrder", { amount: <strong className="text-red-500">12 USD</strong>, })} </p> );}Or, without flipping the global converter, use transX from @mongez/react-localization for the one call.
Persist the locale in a cookie
import { localizationEvents, setCurrentLocaleCode } from "@mongez/localization";
// On boot: read.const match = document.cookie.match(/(?:^|; )locale=([^;]+)/);if (match) setCurrentLocaleCode(decodeURIComponent(match[1]));
// On switch: write.localizationEvents.onChange("localeCode", (next) => { document.cookie = `locale=${encodeURIComponent(next)};path=/;max-age=31536000`;});For SSR you’d parse the cookie from the request on the server, call setCurrentLocaleCode(value) before rendering, and rely on the same browser-side write on subsequent switches.
Pluralize a counter
extend("en", { notification_zero: "No new notifications", notification_one: "1 new notification", notification_many: ":count new notifications", notification_other: ":count new notifications",});
function NotificationBadge({ count }: { count: number }) { return <span>{trans("notification", { count })}</span>;}Pass count: 0, count: 1, count: 7 — each picks the right string.
Mix global and feature translations
// Global keywords for the chrome/shell.extend("en", { logout: "Sign Out", settings: "Settings" });
// Feature-local typed dictionary.const t = transObject({ signIn: { en: "Sign In", ar: "تسجيل الدخول" },});
function UserMenu() { return ( <> <button>{t.signIn}</button> <button>{trans("logout")}</button> <button>{trans("settings")}</button> </> );}Both flow through the same fallback chain and locale-switching events.