- ✅ Installed
i18nextandreact-i18next - ✅ Created i18n configuration (
src/_common/i18n/config.ts) - ✅ Created locale store (
src/_common/store/locale.store.ts) - ✅ Created translation files for all 9 locales:
- en-US (English - United States) FALLBACK
- en-GB (English - United Kingdom)
- en-CA (English - Canada)
- en-AU (English - Australia)
- en-NZ (English - New Zealand)
- fr-FR (French - France)
- de-DE (German - Germany)
- it-IT (Italian - Italy)
- nl-NL (Dutch - Netherlands)
- ✅ Locale selection screen (
src/localeSelection/LocaleSelection.screen.tsx) - ✅ Locale selector component (
src/_common/components/LocaleSelector.tsx) - ✅ Integrated into Router (
src/Router.tsx) - ✅ Integrated into main app (
src/main.tsx)
- ✅ Router.tsx - Error fallback
- ✅ NavigationBar.tsx - Full navigation with all labels and dialogs
- ✅ Boathouse.screen.tsx - Boathouse screen with boat lists
- ✅ Parameters.screen.tsx - Parameter navigation tabs
- ✅ Stats.screen.tsx - Statistics screen with month names and stats
- ✅ Onboarding.screen.tsx - Complete onboarding flow
- ✅ SessionLogs.tsx - Session history with pagination
- ✅ StartSession.Dialog.tsx - Start session dialog
- ✅ StopSession.Dialog.tsx - Stop session dialog
- ✅ Created
boat.rules.i18n.tsfor translated boat type labels
Use this pattern for each component:
- Import useTranslation:
import { useTranslation } from "react-i18next";- Add in component:
const { t } = useTranslation();- Replace hardcoded strings:
// Before:
<button>Valider</button>
// After:
<button>{t("common.confirm")}</button>Boathouse Components:
src/boathouse/components/StartSessionDialog/StartSession.Form.tsxsrc/boathouse/components/StartSessionDialog/BoatSection.tsxsrc/boathouse/components/StartSessionDialog/RowersSection.tsxsrc/boathouse/components/StartSessionDialog/RouteSection.tsxsrc/boathouse/components/StartSessionDialog/CommentSection.tsxsrc/boathouse/components/StartSessionDialog/StartDatetimeSection.tsxsrc/boathouse/components/StartSessionDialog/DurationEstimationSelect.tsxsrc/boathouse/components/StopSessionDialog/StopSession.Form.tsxsrc/boathouse/components/BoatList/*.tsx
Logbook Components:
src/logbook/components/IncidentLogs.tsxsrc/logbook/components/IncidentLogsTable.tsxsrc/logbook/components/SessionLogsTable.tsxsrc/logbook/components/ExportSessions.tsx
Parameters Components:
src/parameters/components/RowersCrud.tsxsrc/parameters/components/BoatsCrud.tsxsrc/parameters/components/MiscParams.tsxsrc/parameters/components/UpdateRower.tsxsrc/parameters/components/UpdateBoat.tsxsrc/parameters/components/BulkUpdateRower.tsxsrc/parameters/components/RowerStats.tsxsrc/parameters/components/BoatStats.tsxsrc/parameters/components/RowerStatsComparisons.tsxsrc/parameters/components/BoatStatsComparisons.tsxsrc/parameters/components/RouteConfigModal.tsxsrc/parameters/components/BoatLevelConfigModal.tsxsrc/parameters/components/BoatLevelSystem.tsxsrc/parameters/components/DeleteDatas.tsxsrc/parameters/components/dialogs/*.tsx
Stats Components:
src/stats/components/SeasonSelector.tsxsrc/stats/components/MonthSelector.tsxsrc/stats/components/StackedBarChart.tsx
Common Components:
src/_common/components/Loading.tsxsrc/_common/components/ErrorBlock.tsxsrc/_common/components/WindowAlert.tsxsrc/_common/components/WindowConfirm.tsxsrc/_common/components/WindowPrompt.tsx
When you find a string that needs translation:
- Add to
src/_common/i18n/locales/en-US.json(English base):
{
"category": {
"newKey": "New English Text"
}
}- Add to
src/_common/i18n/locales/fr-FR.json(French):
{
"category": {
"newKey": "Nouveau texte français"
}
}- Add to all other locale files with appropriate translations.
The translation files are organized into these categories:
common: General UI elements (buttons, labels, etc.)navigation: App navigation and menusonboarding: Onboarding/setup flowboathouse: Boathouse screen specificsession: Session management (start, stop, details)logbook: Logbook and historystats: Statistics screenparameters: Settings/parameters screenboat: Boat-related termsrower: Rower-related termserror: Error messagestime: Time-related terms
For dynamic values:
// In translation file:
"pageOf": "Page {{current}} of {{total}}"
// In component:
{t("session.pageOf", { current: 5, total: 10 })}
// Output: "Page 5 of 10"For plurals, use the i18next convention:
{
"session_one": "{{count}} session",
"session_other": "{{count}} sessions"
}Then use:
t(`stats.session_${count === 1 ? "one" : "other"}`, { count });Use the utility function for boat type labels:
import { getTypeLabelTranslated } from "../_common/business/boat.rules.i18n";
// In component:
const label = getTypeLabelTranslated(boatType, t);- Test Locale Selection: On first launch, you should see the locale selection screen
- Test Translations: Change locale and verify text changes
- Test Fallback: If a translation is missing, it should fall back to en-US
# Run dev server
yarn dev
# Build (includes TypeScript check and tests)
yarn build
# Type check only
yarn tsc
# Lint
yarn lintimport { useTranslation } from "react-i18next";
export const MyComponent = () => {
const { t } = useTranslation();
return <div>{t("category.key")}</div>;
};import { changeLanguage } from "../_common/i18n/config";
import { Locale } from "../_common/store/locale.store";
changeLanguage("fr-FR" as Locale);import { useLocaleStore } from "../_common/store/locale.store";
const { locale } = useLocaleStore();- Go through each component file in the priority list
- Add
useTranslationhook - Replace hardcoded strings with
t()calls - Add missing translation keys to all 9 locale files
- Test each screen by switching locales
- Update utility functions that return user-facing text
- i18next Documentation
- react-i18next Documentation
- Translation files:
src/_common/i18n/locales/*.json