Frontend
Internationalization (i18n)
Internationalization (i18n)
The frontend is fully internationalized with react-i18next. All user-facing
copy is centralized in locale resources — this also satisfies the repository's
"no hardcoded strings" rule.
Setup
apps/web/src/shared/i18nconfigures i18next with the React bindings and a language detector (localStorage + browser language), defaulting to English.- The
I18nProvideris wired inapp/providers.
Languages
en— English (default / fallback).zh— Chinese (Simplified).
Locale resources live in shared/i18n/locales/<lang>/<namespace>.json.
Namespaces
common— shared words, actions, status labels.trips— the trips home.planner— the planner (sidebar, map, schedule, budget, detail).auth— sign-in / sign-up.invite— invite acceptance surface.agent— the trip agent chat.landing— the marketing landing page.error— error surfaces (404 / 500 / 403 / 503 / offline) and photo alt text.
Usage
import { useTranslation } from "react-i18next";
function AddStopButton() {
const { t } = useTranslation("planner");
return <Button>{t("schedule.add")}</Button>;
}Rules:
- No literal user-facing strings in components — always a translation key.
- Keys are namespaced and hierarchical (
schedule.add,budget.settleUp). - Interpolation for dynamic values:
t("itinerary.count", { count }). - Numbers/currency use
Intlvia shared formatters so locale affects grouping; the trip currency (JPY) is fixed by data, not by UI language.
Language switch
A LanguageSwitch coss Select in the app shell lets the user pick a language;
the choice is persisted to localStorage by the detector.
Adding a language
- Add
shared/i18n/locales/<lang>/*.jsonmirroring theenkeys. - Register it in
shared/i18n/index.ts. - Add its label to the language switch.