Skip to content

Add French translation support ✅ - #1877

Closed
comeback01 wants to merge 6 commits into
QuantumNous:mainfrom
comeback01:feat-french-translation
Closed

Add French translation support ✅#1877
comeback01 wants to merge 6 commits into
QuantumNous:mainfrom
comeback01:feat-french-translation

Conversation

@comeback01

@comeback01 comeback01 commented Sep 25, 2025

Copy link
Copy Markdown
Contributor

This pull request adds French language support to the user interface:

  • Created fr.json translation file based on en.json
  • Updated the i18n configuration to include French
  • Modified the language selector to display “Français” with the corresponding flag

Summary by CodeRabbit

  • New Features

    • Added full French (Français) language support and a selectable French option in the language menu.
  • Documentation

    • Added a complete French README with localized project documentation.
    • Updated README language selectors to include a French link.
  • Tests

    • Added an automated verification that checks the language switch to French.

- Création du fichier de traduction `fr.json` en se basant sur `en.json`.
- Mise à jour de la configuration i18n pour inclure la langue française.
- Modification du sélecteur de langue pour afficher l'option "Français" avec le drapeau correspondant.
- Création du fichier `README.fr.md` en se basant sur `README.en.md`.
@coderabbitai

coderabbitai Bot commented Sep 25, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds French localization: new README.fr.md, updates README language links, adds French resources to i18n, extends the header language selector with a French item and flag, changes accessibility label key to common.changeLanguage, and adds a Playwright script to verify switching to French and capture a screenshot.

Changes

Cohort / File(s) Summary of Changes
Docs localization
README.md, README.en.md, README.fr.md
Added a Français link to language switchers in README.md and README.en.md; introduced README.fr.md with full French documentation content.
Frontend i18n & UI
web/src/components/layout/headerbar/LanguageSelector.jsx, web/src/i18n/i18n.js, web/src/i18n/locales/en.json, web/src/i18n/locales/zh.json
Added French flag import and a Dropdown.Item for fr with active styling; changed aria-label key usage to t('common.changeLanguage'); registered fr resources in i18n.js; added common.changeLanguage entries to English and Chinese locale files.
Verification script
jules-scratch/verification/verify_translation.py
New Playwright script that launches headless Chromium, navigates to http://localhost:5173, toggles language to Français, asserts aria-label update, saves verification.png, and exits.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Header as LanguageSelector
  participant I18N as i18n
  participant UI as App UI

  User->>Header: open language menu
  User->>Header: select "Français"
  Header->>I18N: changeLanguage('fr')
  I18N-->>Header: language changed (emit)
  Header->>UI: re-render with 'fr' resources
  UI-->>User: UI displayed in French
  Note over I18N,UI: fallbackLng remains 'zh' for missing keys
Loading
sequenceDiagram
  autonumber
  participant Script as verify_translation.py
  participant Browser as Chromium (headless)
  participant App as http://localhost:5173

  Script->>Browser: launch browser
  Browser->>App: navigate to page
  Script->>Browser: click language toggle (Chinese-labeled)
  Script->>Browser: select "Français"
  Browser->>App: apply i18n 'fr'
  Script->>Browser: expect aria-label uses `common.changeLanguage`
  Script->>Browser: take screenshot -> verification.png
  Script->>Browser: close browser
  Note over Script,Browser: uses explicit waits and a short sleep for UI update
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Poem

I twitch my nose and hop to see,
A tricolor flag and a new "fr" key.
Docs translated, the menu grows bright,
I click, await — the UI turns right.
Snapshot taken — rabbit hops in delight! 🐇📸🇫🇷

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The title accurately summarizes the main change by stating “Add French translation support,” but it includes an emoji, which is considered noise according to repository style guidelines. Remove the checkmark emoji from the title so it reads simply “Add French translation support” to comply with the project’s concise title guidelines.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f35f6e8 and 145b627.

📒 Files selected for processing (2)
  • web/src/i18n/locales/en.json (1 hunks)
  • web/src/i18n/locales/zh.json (1 hunks)
🔇 Additional comments (2)
web/src/i18n/locales/en.json (1)

2128-2131: Nested common namespace looks correct

The ARIA label can now resolve via t('common.changeLanguage'), and the shape matches our other locales. Thanks for aligning this.

web/src/i18n/locales/zh.json (1)

35-38: Chinese locale aligned with nested key path

The nested common.changeLanguage entry keeps Chinese consistent with the other locales, so the language selector will announce the localized string correctly.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
web/src/components/layout/headerbar/LanguageSelector.jsx (2)

23-23: Prefer per-flag imports to minimize bundle risk.

Named exports are usually tree-shaken, but single-file imports are safest across bundlers.

Apply this diff:

-import { CN, GB, FR } from 'country-flag-icons/react/3x2';
+import CN from 'country-flag-icons/react/3x2/CN';
+import GB from 'country-flag-icons/react/3x2/GB';
+import FR from 'country-flag-icons/react/3x2/FR';

55-58: Use stable i18n keys and add a test id for robust e2e selection.

Avoid using a natural-language key ('切换语言') and expose a data-testid for Playwright.

Apply this diff:

-      <Button
-        icon={<Languages size={18} />}
-        aria-label={t('切换语言')}
+      <Button
+        icon={<Languages size={18} />}
+        aria-label={t('common.changeLanguage')}
+        data-testid='language-selector'
         theme='borderless'

Add translations for common.changeLanguage in all locales, for example:

  • web/src/i18n/locales/zh.json:
{ "common": { "changeLanguage": "切换语言" } }
  • web/src/i18n/locales/en.json:
{ "common": { "changeLanguage": "Change language" } }
  • web/src/i18n/locales/fr.json:
{ "common": { "changeLanguage": "Changer de langue" } }
jules-scratch/verification/verify_translation.py (1)

1-43: Make the test resilient to initial locale and remove fixed sleeps.

Handle both Chinese/English initial states and rely on expect instead of time.sleep.

Apply this diff:

-from playwright.sync_api import sync_playwright, expect
+from playwright.sync_api import sync_playwright, expect
+from playwright.sync_api import TimeoutError as PWTimeoutError
@@
-    # The aria-label is in Chinese in the source, so we use that.
-    language_button = page.get_by_role("button", name="切换语言")
-
-    # Wait for the button to be visible
-    expect(language_button).to_be_visible()
+    # Locate the language button (support CN or EN initial states)
+    btn_cn = page.get_by_role("button", name="切换语言")
+    btn_en = page.get_by_role("button", name="Change language")
+    language_button = btn_cn if btn_cn.count() else btn_en
+    expect(language_button).to_be_visible()
@@
-    # Wait for the language switch to apply
-    time.sleep(2)  # Wait for 2 seconds
-
-    # Now the aria-label should be in French
+    # Now the aria-label should be in French (wait up to 10s)
     expect(page.get_by_role("button", name="Changer de langue")).to_be_visible(timeout=10000)
+    # Optional: verify i18next persisted language
+    try:
+        lang = page.evaluate("() => localStorage.getItem('i18nextLng')")
+        print("i18nextLng =", lang)
+    except PWTimeoutError:
+        pass

If you adopt data-testid in LanguageSelector, prefer:

  • language_button = page.get_by_test_id("language-selector")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6992fd2 and cd923ee.

⛔ Files ignored due to path filters (2)
  • bun_output.log is excluded by !**/*.log
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • README.en.md (1 hunks)
  • README.fr.md (1 hunks)
  • README.md (1 hunks)
  • jules-scratch/verification/verify_translation.py (1 hunks)
  • web/src/components/layout/headerbar/LanguageSelector.jsx (2 hunks)
  • web/src/i18n/i18n.js (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
web/src/components/layout/headerbar/LanguageSelector.jsx (1)
web/src/hooks/common/useHeaderBar.js (1)
  • currentLang (39-39)
🪛 markdownlint-cli2 (0.18.1)
README.fr.md

37-37: Blank line inside blockquote

(MD028, no-blanks-blockquote)

🔇 Additional comments (4)
README.en.md (1)

2-2: Add Français link — looks good.

Verify the README.fr.md path resolves and the language order matches other READMEs.

README.fr.md (1)

1-216: Solid French localization added.

Run markdownlint to ensure no MD028 (“no blank lines in blockquotes”) violations remain in this file.

README.md (1)

2-2: Français link added — consistent with other READMEs.

Confirm the target file exists in main and the link isn’t broken post-merge.

web/src/components/layout/headerbar/LanguageSelector.jsx (1)

45-51: French option wiring — LGTM.

Good use of FR flag and active state.

Comment thread web/src/i18n/i18n.js
- Added `common.changeLanguage` key to `en.json`, `fr.json`, and `zh.json`.
- Updated `LanguageSelector.jsx` to use the new shared key.
- Completed `fr.json` with all keys from `en.json` and `zh.json`.
- Added translations for `closeSidebar`, `pricing`, and `language`.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd923ee and f35f6e8.

📒 Files selected for processing (3)
  • web/src/components/layout/headerbar/LanguageSelector.jsx (2 hunks)
  • web/src/i18n/locales/en.json (1 hunks)
  • web/src/i18n/locales/zh.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
web/src/components/layout/headerbar/LanguageSelector.jsx (1)
web/src/hooks/common/useHeaderBar.js (1)
  • currentLang (39-39)
🔇 Additional comments (3)
web/src/components/layout/headerbar/LanguageSelector.jsx (3)

23-23: FR flag import aligns with new locale
Importing FR alongside CN and GB keeps the flag set consistent with the supported languages.


45-51: French dropdown entry looks good
The new item mirrors the existing pattern, calls onLanguageChange('fr'), and uses the correct flag/title.


57-57: common.changeLanguage is present in all locale JSON files Confirmed the key exists in en.json, fr.json, and zh.json.

Comment thread web/src/i18n/locales/en.json Outdated
Comment thread web/src/i18n/locales/zh.json Outdated
- Restructured the `common.changeLanguage` key to be nested under a `common` object in `en.json`, `fr.json`, and `zh.json`.
- This change improves the organization of the translation files and aligns with best practices for i18next.
@comeback01

Copy link
Copy Markdown
Contributor Author

Closing this pull request as it has been superseded by #1889, which contains the same changes rebased on the latest main branch.

@comeback01 comeback01 closed this Sep 27, 2025
@comeback01
comeback01 deleted the feat-french-translation branch September 28, 2025 10:14
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.

1 participant