docs: improve react-intl documentation for React Server Components#3085
docs: improve react-intl documentation for React Server Components#3085
Conversation
- Document createIntl from @formatjs/intl as the recommended approach for i18n in Server Components (context-free, full formatting support) - Add limitations section for plain messages['key'] lookup pattern (only works for pre-formatted strings, not ICU placeholders) - Document Rails pre-formatting as a valid alternative approach - Reconcile build-time (config.i18n_dir) vs controller-props approaches with comparison table explaining when to use each - Fix vague i18next claim with concrete per-request initialization guidance - Add RSC cross-reference section to the build-time i18n docs - Update compatibility decision matrix with createIntl recommendation Fixes #3081 Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
WalkthroughDocumentation updates clarify React Server Component i18n patterns: add guidance for using Changes
Sequence Diagram(s)sequenceDiagram
participant Rails as Rails Controller
participant RSC as React Server Component
participant FormatJS as createIntl (FormatJS)
rect rgba(200,230,255,0.5)
Rails->>RSC: Option A — pass pre-formatted strings (I18n.t(...))
RSC-->>Rails: Render with plain props
end
rect rgba(220,255,200,0.5)
RSC->>FormatJS: Option B — import createIntl({locale,messages})
FormatJS-->>RSC: formatMessage / formatNumber / pluralize
RSC-->>Client: Rendered HTML (no Intl context)
end
rect rgba(255,240,200,0.5)
Client->>Client: Client Components use <IntlProvider> + useIntl()
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Greptile SummaryThis PR improves the i18n documentation for React Server Components by documenting
Confidence Score: 4/5Safe to merge after fixing the out-of-order mistake numbering (1 → 2 → 5 → 3 → 4) in rsc-context-and-state.md. One P1 documentation correctness issue: the newly inserted 'Mistake 5' section is mis-numbered and sits between Mistake 2 and Mistake 3, which will confuse readers. The rest of the content — createIntl guidance, comparison table, and third-party-libs matrix updates — is accurate and well-structured. docs/oss/migrating/rsc-context-and-state.md — fix the Mistake 5 heading to Mistake 3 and renumber subsequent mistakes accordingly.
|
| Filename | Overview |
|---|---|
| docs/oss/building-features/i18n.md | Adds a short RSC cross-reference section pointing to createIntl and Rails pre-formatting; content is accurate and links resolve correctly. |
| docs/oss/migrating/rsc-context-and-state.md | Expands i18n Provider section with createIntl guidance and comparison table; introduces a numbering error in the Common Mistakes list (5 appears between 2 and 3). |
| docs/oss/migrating/rsc-third-party-libs.md | Updates i18n rows in both tables to reference createIntl and per-request i18next.createInstance(); changes are accurate and consistent with the other docs. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Server Component needs i18n] --> B{Has interpolation\nor pluralization?}
B -- No --> C[Plain messages lookup\nmessages'key']
B -- Yes --> D{Where to format?}
D -- Server --> E[createIntl from @formatjs/intl\nfull formatting, no Context needed]
D -- Rails --> F[Rails pre-formatting\nI18n.t with variables in controller]
A --> G[Child Client Components]
G --> H[IntlProvider + useIntl\nstandard react-intl Context]
E --> I[Pass formatted strings\nto JSX directly]
F --> I
Reviews (1): Last reviewed commit: "docs: improve react-intl documentation f..." | Re-trigger Greptile
Review: docs: improve react-intl documentation for React Server ComponentsGood addition overall — the Issues to fix1. Mistake numbering out of order (inline comment on line 530) 2. Import path inconsistency: 3. Malformed BAD/GOOD code block in Mistake 5 (inline comment on lines 534–542) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 345670f2fa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
🧹 Nitpick comments (1)
docs/oss/migrating/rsc-third-party-libs.md (1)
254-258: Consider mentioning next-i18next v16'sgetT()as a more native RSC-friendly alternative.The
i18next.createInstance()pattern for per-request Server Component initialization is correctly documented and supported. However, the guidance omits a newer, more RSC-native approach: next-i18next v16 providesgetT()specifically for Server Components, eliminating the need for manual hook avoidance and initialization management. Consider adding this as the recommended pattern while keepingcreateInstance()as a valid but more manual fallback.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/oss/migrating/rsc-third-party-libs.md` around lines 254 - 258, The doc omits next-i18next v16's Server Component helper; update the i18next/react-i18next row to mention next-i18next v16's getT() as the recommended RSC-friendly approach, while keeping the existing i18next.createInstance() per-request pattern as a manual fallback; reference the symbols `getT()`, `i18next.createInstance()` and `useTranslation` in the Notes or RSC Pattern column so readers can find both the native Server Component API and the older hook/instance-based approach.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@docs/oss/migrating/rsc-third-party-libs.md`:
- Around line 254-258: The doc omits next-i18next v16's Server Component helper;
update the i18next/react-i18next row to mention next-i18next v16's getT() as the
recommended RSC-friendly approach, while keeping the existing
i18next.createInstance() per-request pattern as a manual fallback; reference the
symbols `getT()`, `i18next.createInstance()` and `useTranslation` in the Notes
or RSC Pattern column so readers can find both the native Server Component API
and the older hook/instance-based approach.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 412f53c4-59b3-42ff-91c3-5224d0d32f91
📒 Files selected for processing (3)
docs/oss/building-features/i18n.mddocs/oss/migrating/rsc-context-and-state.mddocs/oss/migrating/rsc-third-party-libs.md
|
Review triage follow-up for skipped items:
All must-fix items were applied in commit 8c29975. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8c29975ed3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Good documentation improvement overall. The createIntl recommendation fills a real gap for RSC i18n, the comparison table is useful, and renumbering the Common Mistakes section is clean housekeeping. Package name inconsistency (two places): The text in i18n.md and rsc-third-party-libs.md refers to createIntl as coming from @formatjs/intl, but the code example in rsc-context-and-state.md correctly imports it from react-intl. Both exports exist, but react-intl v5+ re-exports createIntl - users who already have react-intl installed do not need a separate @formatjs/intl dependency. See inline comments on both files. createIntlCache missing from recommended pattern: Without createIntlCache, expensive Intl.NumberFormat and Intl.DateTimeFormat instances are reconstructed on every request. FormatJS recommends passing a cache as the second argument to createIntl. The cache stores only Intl constructor results (no request data), so it is safe to share at module scope. Worth adding to the canonical example or at minimum as a performance note. See inline comment. Minor - InteractiveFilters message ID assumption: The InteractiveFilters Client Component formats the id filters.apply, but the IntlProvider receives messages scoped to I18n.t(product_page). This works only if the product_page YAML contains a filters.apply sub-key - an assumption that is not stated. A one-line comment in the example would clarify. |
- Change @formatjs/intl → react-intl in i18n.md and rsc-third-party-libs.md to match code examples (react-intl v5+ re-exports createIntl) - Add createIntlCache to the recommended Server Component pattern to avoid recreating expensive Intl constructors on every request Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Review follow-up — commit 1c5555cAddressed all outstanding review comments from the second review round: Fixed (3 items):
Skipped (replied with rationale):
All 10 review threads resolved (6 from first round + 4 from second round). |
ReviewGood, accurate documentation overall. The Two issues to fix1. Inconsistent The "GOOD" example in Mistake 3 calls 2. Module-level cache explanation could be more precise (inline comment at line 421) The note says the cache is "safe to share at module scope" — which is true — but doesn't spell out that module-level variables in Node.js are shared across all concurrent requests for the life of the process. The safety relies on the cache holding only Minor observations (no action needed)
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1c5555c80a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- Add createIntlCache to GOOD snippet in Mistake 3 to match recommended pattern - Clarify module-level cache note: explicit about Node.js process-lifetime sharing and that cache holds only Intl constructor instances (no request data) - Change "flat or nested" to "Flat (required by createIntl)" in comparison table Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Review follow-up — commit eb62286Addressed all outstanding review comments from the third review round: Fixed (3 items):
Skipped (replied with rationale):
All 14 review threads now resolved across 3 review rounds. |
| ```jsx | ||
| // GOOD: Use createIntl to format with variable substitution | ||
| import { createIntl, createIntlCache } from 'react-intl'; | ||
| const cache = createIntlCache(); | ||
| const intl = createIntl({ locale, messages }, cache); | ||
| const greeting = intl.formatMessage({ id: 'greeting' }, { name: 'John' }); | ||
| ``` |
There was a problem hiding this comment.
The "GOOD" example places createIntl(...) and greeting at module scope, but locale and messages are not defined there — this would throw ReferenceError: locale is not defined if copied literally.
Compare with the recommended createIntl example above: cache is at module scope, while intl is created inside the component function where locale and messages are in scope.
| ```jsx | |
| // GOOD: Use createIntl to format with variable substitution | |
| import { createIntl, createIntlCache } from 'react-intl'; | |
| const cache = createIntlCache(); | |
| const intl = createIntl({ locale, messages }, cache); | |
| const greeting = intl.formatMessage({ id: 'greeting' }, { name: 'John' }); | |
| ``` | |
| ```jsx | |
| // GOOD: Use createIntl to format with variable substitution | |
| import { createIntl, createIntlCache } from 'react-intl'; | |
| // Module-level — safe, caches only Intl constructors | |
| const cache = createIntlCache(); | |
| export default function MyComponent({ locale, messages }) { | |
| const intl = createIntl({ locale, messages }, cache); | |
| const greeting = intl.formatMessage({ id: 'greeting' }, { name: 'John' }); | |
| return <p>{greeting}</p>; | |
| } |
| | Approach | Source | Key format | Best for | | ||
| | ------------------------------ | -------------------------- | ------------------------------- | --------------------------------------------------------------------------------------- | | ||
| | Build-time (`config.i18n_dir`) | YAML → compiled JSON/JS | Flat: `"product.title"` | Static translations shared across pages; client-side `react-intl` with `defineMessages` | | ||
| | Controller-props (`I18n.t`) | Rails I18n at request time | Flat (required by `createIntl`) | Page-specific translations; pre-formatted strings with variables; RSC `createIntl` | |
There was a problem hiding this comment.
"Flat (required by createIntl)" in the "Key format" column is slightly misleading. createIntl accepts any flat Record<string, string> — both approaches (build-time and controller-props) produce flat key→string objects for react-intl. The real distinction is who owns the key namespace, not that createIntl imposes the flat requirement. Consider rewording to something like "Flat map (ID → string)" to avoid implying that only this approach satisfies createIntl's contract.
| | Controller-props (`I18n.t`) | Rails I18n at request time | Flat (required by `createIntl`) | Page-specific translations; pre-formatted strings with variables; RSC `createIntl` | | |
| | Controller-props (`I18n.t`) | Rails I18n at request time | Flat map (ID → string) | Page-specific translations; pre-formatted strings with variables; RSC `createIntl` | |
|
Overall this is a well-structured documentation improvement. The createIntl guidance is technically accurate, the build-time vs. controller-props comparison table is helpful, and the re-numbering of Common Mistakes keeps the section coherent. One bug in a code example: the Mistake 3 GOOD example puts createIntl and formatMessage at module scope where locale and messages are undefined; copied literally it would throw ReferenceError. Inline suggestion posted. Minor wording suggestion: the table column says Flat (required by createIntl) for controller-props key format, but both approaches produce a flat ID-to-string map that createIntl accepts; inline suggestion posted. Nits: PR description references @formatjs/intl while code examples import from react-intl (both are correct since react-intl re-exports createIntl from @formatjs/intl). The cache safety note is accurate; optionally noting the cache is keyed by locale + format descriptor would pre-empt multi-locale questions. |
…3085) ## Summary - Document `createIntl` from `@formatjs/intl` as the recommended approach for i18n in Server Components — a context-free API with full interpolation, pluralization, and date/number formatting - Add limitations section for the plain `messages['key']` lookup pattern (only works for pre-formatted strings, renders ICU `{variable}` placeholders as literal text) - Document Rails pre-formatting (`I18n.t('key', name: value)`) as a valid alternative for Server Components - Add comparison table reconciling build-time (`config.i18n_dir`) vs controller-props i18n approaches - Fix vague i18next claim in `rsc-third-party-libs.md` with concrete per-request `createInstance()` guidance - Add RSC cross-reference section to the build-time i18n docs - Update compatibility decision matrix with `createIntl` recommendation Fixes #3081 ## Test plan - [ ] Verify all internal markdown links resolve correctly - [ ] Review `createIntl` code examples for accuracy against FormatJS docs - [ ] Confirm build-time vs controller-props comparison table is accurate 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: documentation-only updates that don’t change runtime code, limited to guidance/examples for i18n usage in RSC. > > **Overview** > Adds **React Server Components i18n guidance** across the docs, recommending `react-intl`’s context-free `createIntl` API for Server Components and documenting Rails-side pre-formatting as an alternative. > > Clarifies the limitations of direct `messages['key']` lookups with ICU placeholders, adds a build-time vs controller-props comparison table, and updates the RSC third-party compatibility docs/matrix to reflect the `createIntl` recommendation and more concrete `i18next` per-request setup notes. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit eb62286. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added a comprehensive guide for internationalization with React Server Components, recommending server-side formatting patterns and a controller pre-formatting alternative. * Reintroduced explicit client-side provider pattern for Client Components. * Added a build-time vs request-time comparison table and updated third-party library compatibility guidance (including per-request i18next considerations). * Expanded common mistakes with placeholder and formatting guidance. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
…3085) ## Summary - Document `createIntl` from `@formatjs/intl` as the recommended approach for i18n in Server Components — a context-free API with full interpolation, pluralization, and date/number formatting - Add limitations section for the plain `messages['key']` lookup pattern (only works for pre-formatted strings, renders ICU `{variable}` placeholders as literal text) - Document Rails pre-formatting (`I18n.t('key', name: value)`) as a valid alternative for Server Components - Add comparison table reconciling build-time (`config.i18n_dir`) vs controller-props i18n approaches - Fix vague i18next claim in `rsc-third-party-libs.md` with concrete per-request `createInstance()` guidance - Add RSC cross-reference section to the build-time i18n docs - Update compatibility decision matrix with `createIntl` recommendation Fixes #3081 ## Test plan - [ ] Verify all internal markdown links resolve correctly - [ ] Review `createIntl` code examples for accuracy against FormatJS docs - [ ] Confirm build-time vs controller-props comparison table is accurate 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: documentation-only updates that don’t change runtime code, limited to guidance/examples for i18n usage in RSC. > > **Overview** > Adds **React Server Components i18n guidance** across the docs, recommending `react-intl`’s context-free `createIntl` API for Server Components and documenting Rails-side pre-formatting as an alternative. > > Clarifies the limitations of direct `messages['key']` lookups with ICU placeholders, adds a build-time vs controller-props comparison table, and updates the RSC third-party compatibility docs/matrix to reflect the `createIntl` recommendation and more concrete `i18next` per-request setup notes. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit eb62286. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added a comprehensive guide for internationalization with React Server Components, recommending server-side formatting patterns and a controller pre-formatting alternative. * Reintroduced explicit client-side provider pattern for Client Components. * Added a build-time vs request-time comparison table and updated third-party library compatibility guidance (including per-request i18next considerations). * Expanded common mistakes with placeholder and formatting guidance. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
…3085) ## Summary - Document `createIntl` from `@formatjs/intl` as the recommended approach for i18n in Server Components — a context-free API with full interpolation, pluralization, and date/number formatting - Add limitations section for the plain `messages['key']` lookup pattern (only works for pre-formatted strings, renders ICU `{variable}` placeholders as literal text) - Document Rails pre-formatting (`I18n.t('key', name: value)`) as a valid alternative for Server Components - Add comparison table reconciling build-time (`config.i18n_dir`) vs controller-props i18n approaches - Fix vague i18next claim in `rsc-third-party-libs.md` with concrete per-request `createInstance()` guidance - Add RSC cross-reference section to the build-time i18n docs - Update compatibility decision matrix with `createIntl` recommendation Fixes #3081 ## Test plan - [ ] Verify all internal markdown links resolve correctly - [ ] Review `createIntl` code examples for accuracy against FormatJS docs - [ ] Confirm build-time vs controller-props comparison table is accurate 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: documentation-only updates that don’t change runtime code, limited to guidance/examples for i18n usage in RSC. > > **Overview** > Adds **React Server Components i18n guidance** across the docs, recommending `react-intl`’s context-free `createIntl` API for Server Components and documenting Rails-side pre-formatting as an alternative. > > Clarifies the limitations of direct `messages['key']` lookups with ICU placeholders, adds a build-time vs controller-props comparison table, and updates the RSC third-party compatibility docs/matrix to reflect the `createIntl` recommendation and more concrete `i18next` per-request setup notes. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit eb62286. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added a comprehensive guide for internationalization with React Server Components, recommending server-side formatting patterns and a controller pre-formatting alternative. * Reintroduced explicit client-side provider pattern for Client Components. * Added a build-time vs request-time comparison table and updated third-party library compatibility guidance (including per-request i18next considerations). * Expanded common mistakes with placeholder and formatting guidance. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
…ages * origin/main: (44 commits) Consolidate CSP nonce sanitization into shared module (#2828) Add comprehensive --rsc-pro generator tests (#3098) fix: cross-env validation and docs for renderer password (#3090) Improve package metadata and Pro upgrade CTAs (#3112) docs: standardize warning syntax to GFM alert format (#3115) docs: improve react-intl documentation for React Server Components (#3085) Fix generator CI SSR regression on main (#3110) Refocus GitHub README on docs navigation (#3113) Add manual dev environment testing checklist for coding agents (#3074) Bump version to 16.6.0 Update CHANGELOG.md for 16.6.0 (#3078) fix: node-renderer diagnostic improvements (#3086) fix: pin third-party npm deps in generator to prevent peer dep conflicts (#3083) chore(deps): bump lodash from 4.17.23 to 4.18.1 in the npm-security group across 1 directory (#2920) fix: refactor formatExceptionMessage to accept generic request context (#2877) Bump version to 16.6.0.rc.1 Update CHANGELOG.md for 16.6.0.rc.1 (#3079) Update CHANGELOG.md unreleased section (#3077) Fix Content-Length mismatch and null renderingRequest errors in node renderer (#3069) Improve memory debugging docs with simpler heap snapshot approach (#3072) ... # Conflicts: # docs/pro/home-pro.md # docs/pro/react-on-rails-pro.md # docs/sidebars.ts
Summary
createIntlfrom@formatjs/intlas the recommended approach for i18n in Server Components — a context-free API with full interpolation, pluralization, and date/number formattingmessages['key']lookup pattern (only works for pre-formatted strings, renders ICU{variable}placeholders as literal text)I18n.t('key', name: value)) as a valid alternative for Server Componentsconfig.i18n_dir) vs controller-props i18n approachesrsc-third-party-libs.mdwith concrete per-requestcreateInstance()guidancecreateIntlrecommendationFixes #3081
Test plan
createIntlcode examples for accuracy against FormatJS docs🤖 Generated with Claude Code
Note
Low Risk
Low risk: documentation-only updates that don’t change runtime code, limited to guidance/examples for i18n usage in RSC.
Overview
Adds React Server Components i18n guidance across the docs, recommending
react-intl’s context-freecreateIntlAPI for Server Components and documenting Rails-side pre-formatting as an alternative.Clarifies the limitations of direct
messages['key']lookups with ICU placeholders, adds a build-time vs controller-props comparison table, and updates the RSC third-party compatibility docs/matrix to reflect thecreateIntlrecommendation and more concretei18nextper-request setup notes.Reviewed by Cursor Bugbot for commit eb62286. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit