Skip to content

feat(frontend): add react-i18next FR + EN setup (T-125)#59

Merged
mpiton merged 1 commit into
mainfrom
feat/T-125-i18n-setup
May 10, 2026
Merged

feat(frontend): add react-i18next FR + EN setup (T-125)#59
mpiton merged 1 commit into
mainfrom
feat/T-125-i18n-setup

Conversation

@mpiton
Copy link
Copy Markdown
Owner

@mpiton mpiton commented May 10, 2026

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 ergonomic useT(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.language auto-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 convenience useT(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 — added src/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.
  • Snapshots: sidebar-tasks-en → "Tasks", sidebar-tasks-fr → "Tâches".

Related Issues

Notes for Reviewer

  • JSON resources are bundled at build time (zero runtime fetch). Module exports are ignored by knip until T-128/T-129 consume them — follows existing pattern for src/shared/components/ui/** and src/shared/types/**.
  • No persistence of language preference across page reloads (MVP scope); deferred to future sprint if needed.
  • Type-safe Namespace type includes all three namespaces; consumers can use useT("sidebar") for IDE autocomplete on key names (future enhancement with typed-i18next if keys grow complex).

Checklist

  • Tests added (9 cases, all passing)
  • Docs updated (CHANGELOG.md)
  • No secrets committed
  • Self-reviewed
  • CI-relevant files formatted and linted (oxlint 0 warnings, oxfmt clean, tsc clean)

Summary by CodeRabbit

  • New Features
    • Added English and French language support throughout the application.
    • Implemented automatic browser language detection to display content in your preferred language.
    • Localized key features including navigation, common actions, and onboarding experience.

Review Change Stack

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
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 10, 2026

📝 Walkthrough

Walkthrough

The 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.

Changes

React i18n Feature Setup

Layer / File(s) Summary
Locale & Namespace Types
src/shared/i18n/i18n.ts
Exports SUPPORTED_LOCALES (en, fr) and NAMESPACES (common, sidebar, onboarding) as const arrays, deriving Locale and Namespace type aliases.
Locale Detection & i18next Init
src/shared/i18n/i18n.ts
Implements detectInitialLocale() reading from navigator.language with SSR-safe fallback to "en"; initializes i18next with React integration, namespace configuration, and JSON resource loading.
Locale Resources
src/shared/i18n/locales/en.json, src/shared/i18n/locales/fr.json
Provides English and French UI strings across common (actions, dark/light mode), sidebar (navigation), and onboarding (welcome, steps) namespaces.
Public API & useT Hook
src/shared/i18n/index.ts
Re-exports i18n, constants, types, and useTranslation; exports new useT(ns?) hook that returns namespace-scoped translator function.
App Root Provider
src/main.tsx
Wraps <App /> with <I18nextProvider i18n={i18n}>, adding translation context at the application entry point.
Tests
src/shared/i18n/__tests__/i18n.test.tsx
Validates namespace declarations, language fallback, translation outputs across locales, useT hook scoping, DOM updates on language switch, and react-i18next interoperability.
Configuration & Docs
knip.json, CHANGELOG.md
Adds knip ignore entry for src/shared/i18n/**; documents feature in changelog with test and tooling validation.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • mpiton/forgent#56: Establishes the i18next and react-i18next npm dependencies that this PR's i18n module directly uses and integrates with the app.

Poem

🐰 A translator hops from shore to shore,
EN to FR, and back once more,
Navigator whispers, choose the tongue,
With namespaces neat and useT well-sung!
I18n blooms—language flows like clover. 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(frontend): add react-i18next FR + EN setup (T-125)' accurately summarizes the main change—implementing react-i18next internationalization for French and English with specific task reference.
Linked Issues check ✅ Passed All acceptance criteria from issue #40 are met: translations work correctly (en.json/fr.json seeded), locale auto-detection via navigator.language implemented, TypeScript build passes, and vitest snapshot tests included.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #40 objectives: i18n initialization, resource files, exports/helpers, app integration, tests, and tooling updates—no extraneous modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/T-125-i18n-setup

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
knip.json (1)

16-16: ⚡ Quick win

Avoid masking active i18n modules in knip ignore.

Now that src/shared/i18n is 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

📥 Commits

Reviewing files that changed from the base of the PR and between dba3c63 and f5b9179.

⛔ Files ignored due to path filters (1)
  • src/shared/i18n/__tests__/__snapshots__/i18n.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • CHANGELOG.md
  • knip.json
  • src/main.tsx
  • src/shared/i18n/__tests__/i18n.test.tsx
  • src/shared/i18n/i18n.ts
  • src/shared/i18n/index.ts
  • src/shared/i18n/locales/en.json
  • src/shared/i18n/locales/fr.json

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 10, 2026

Merging this PR will not alter performance

✅ 7 untouched benchmarks


Comparing feat/T-125-i18n-setup (f5b9179) with main (dba3c63)

Open in CodSpeed

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 9 files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[T-125] i18n setup react-i18next FR + EN

1 participant