feat(frontend): add react-i18next FR + EN setup (T-125)#59
Conversation
Initializes i18next with bundled JSON resources, navigator.language auto-detection (fr* → fr, else en), fallback en, and namespaces common/sidebar/onboarding seeded for Sidebar (T-128) and WelcomeScreen (T-129). Wraps App with I18nextProvider; exposes useT(ns) hook plus typed Locale/Namespace constants. Closes #40. - src/shared/i18n/{i18n,index}.ts + locales/{en,fr}.json - src/shared/i18n/__tests__/i18n.test.tsx (9 cases incl. per-locale snapshots) - src/main.tsx wrapped in <I18nextProvider> - knip.json ignore src/shared/i18n/** (public shared module pattern) - CHANGELOG.md Unreleased entry
📝 WalkthroughWalkthroughThe PR establishes a complete internationalization system using i18next and react-i18next, initializing supported locales (EN, FR) with bundled JSON resources, auto-detecting language via navigator.language, and providing a useT hook for scoped translation access. The app root is wrapped with I18nextProvider, and comprehensive tests validate the setup across both locales. ChangesReact i18n Feature Setup
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
knip.json (1)
16-16: ⚡ Quick winAvoid masking active i18n modules in knip ignore.
Now that
src/shared/i18nis wired into the app, ignoring the full subtree weakens dead-code checks for a live module. Prefer removing this ignore entry (or scoping it only to a truly generated/temporary subset).♻️ Suggested change
"ignore": [ "src/vite-env.d.ts", "src/shared/types/**", "src/shared/components/ui/**", - "src/shared/i18n/**", "src/shared/lib/cn.ts",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@knip.json` at line 16, Remove the broad knip ignore pattern "src/shared/i18n/**" since that masks an active module; instead delete that entry from knip.json or replace it with a narrowly-scoped pattern that only targets truly generated/temporary files (e.g., a specific generated directory or filename pattern under src/shared/i18n) so the live i18n module (src/shared/i18n) remains included in dead-code analysis.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@knip.json`:
- Line 16: Remove the broad knip ignore pattern "src/shared/i18n/**" since that
masks an active module; instead delete that entry from knip.json or replace it
with a narrowly-scoped pattern that only targets truly generated/temporary files
(e.g., a specific generated directory or filename pattern under src/shared/i18n)
so the live i18n module (src/shared/i18n) remains included in dead-code
analysis.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ae725c54-4e8f-47bc-b8a4-261db641e056
⛔ Files ignored due to path filters (1)
src/shared/i18n/__tests__/__snapshots__/i18n.test.tsx.snapis excluded by!**/*.snap
📒 Files selected for processing (8)
CHANGELOG.mdknip.jsonsrc/main.tsxsrc/shared/i18n/__tests__/i18n.test.tsxsrc/shared/i18n/i18n.tssrc/shared/i18n/index.tssrc/shared/i18n/locales/en.jsonsrc/shared/i18n/locales/fr.json
Summary
Implements react-i18next setup for FR + EN support at v0.1 launch (ADR-010, PRD F-076). Auto-detects user locale via
navigator.language, provides ergonomicuseT(ns)hook, and seeds three namespaces (common, sidebar, onboarding) for downstream Sidebar (T-128) and WelcomeScreen (T-129) tasks. Closes #40.Why
ADR-010 mandates FR + EN translations from launch. Sidebar and WelcomeScreen tasks (T-128, T-129) depend on this setup to use localized strings via
t().Changes
src/shared/i18n/i18n.ts— i18next init with bundled JSON,navigator.languageauto-detection (fr* → fr, else en), fallback en, namespaces [common, sidebar, onboarding], SSR-safe guard.src/shared/i18n/locales/{en,fr}.json— seeded strings: common (loading, error, retry, cancel, save, close, dark_mode, light_mode), sidebar (tasks, roadmap, insights, ideation, settings, expand, collapse), onboarding (welcome/step substeps).src/shared/i18n/index.ts— re-exports i18n instance, useTranslation, public types (Locale, Namespace), constants (NAMESPACES, SUPPORTED_LOCALES), and convenienceuseT(ns?)hook.src/shared/i18n/__tests__/i18n.test.tsx— 9 vitest cases: namespace declaration, fallback behavior, en/fr resolution for sidebar/common/nested onboarding, useT scoped translator, per-locale snapshots, useTranslation interop.src/main.tsx— wrapped<App />in<I18nextProvider i18n={i18n}>.knip.json— addedsrc/shared/i18n/**to ignore list (public shared module, consumed by T-128/T-129).CHANGELOG.md— Unreleased entry documenting feature + test coverage.Testing
pnpm exec vitest run— 59/59 tests pass (9 new i18n cases).pnpm exec tsc -b— no errors.pnpm exec oxlint .— 0 warnings, 0 errors.pnpm exec oxfmt --check src/shared/i18n src/main.tsx— all files properly formatted.sidebar-tasks-en→ "Tasks",sidebar-tasks-fr→ "Tâches".Related Issues
Notes for Reviewer
src/shared/components/ui/**andsrc/shared/types/**.Namespacetype includes all three namespaces; consumers can useuseT("sidebar")for IDE autocomplete on key names (future enhancement with typed-i18next if keys grow complex).Checklist
Summary by CodeRabbit