Skip to content

fix(react): allow explicit locale for static server rendering - #3528

Open
floze-the-genius wants to merge 3 commits into
tolgee:mainfrom
floze-the-genius:fix/3526-static-app-router-locale
Open

floze-the-genius wants to merge 3 commits into
tolgee:mainfrom
floze-the-genius:fix/3526-static-app-router-locale

Conversation

@floze-the-genius

@floze-the-genius floze-the-genius commented Jul 19, 2026

Copy link
Copy Markdown

Problem

Next.js App Router applications that already know the locale from route params still had to invoke the request-bound locale resolver. That resolver calls headers(), so otherwise deterministic generateStaticParams routes could not be rendered as SSG pages. This is the limitation confirmed in #3526.

Solution

  • allow createServerInstance callers to pass an explicit locale to getTolgee and getTranslate
  • allow the server T component to accept an explicit locale while preserving every existing TProps field
  • skip request-bound locale detection when an explicit locale is available
  • add a Next App Router generateStaticParams regression route and example guidance

The API is additive; calls without a locale keep the existing resolver behavior.

Verification

  • pnpm --filter @tolgee/react... build
  • pnpm --filter @tolgee/react test: 38/38 passed
  • pnpm --dir testapps/next-app-intl build: emitted /en/ssg, /cs/ssg, /de/ssg, and /fr/ssg as SSG routes
  • focused ESLint and Prettier checks
  • git diff --check
  • exact 2/2 range-diff after rebase onto current main
  • independent API and SSG review completed with no blocking findings

Closes #3526.

AI assistance

I used OpenAI Codex to assist with implementation, testing, and rebase validation. I reviewed and understand the changes.

Summary by CodeRabbit

  • New Features

    • Server-side translation helpers now support an explicitly selected locale.
    • The server translation component can render content using a specified locale.
    • Added support and examples for statically generated, locale-specific pages.
  • Documentation

    • Added guidance for using route-provided locales during static rendering.
  • Tests

    • Added coverage for default and explicitly selected locale behavior across server translation APIs.

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 41bd7570-f833-487b-b782-748656f60b8d

📥 Commits

Reviewing files that changed from the base of the PR and between 4a96ccc and d5d9e43.

📒 Files selected for processing (4)
  • packages/react/src/createServerInstance.spec.tsx
  • packages/react/src/createServerInstance.tsx
  • testapps/next-app-intl/README.md
  • testapps/next-app-intl/src/app/[locale]/layout.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • testapps/next-app-intl/README.md
  • packages/react/src/createServerInstance.spec.tsx
  • testapps/next-app-intl/src/app/[locale]/layout.tsx

Walkthrough

createServerInstance now accepts explicit locales for Tolgee creation and translation lookup. Tests cover default and explicit locale paths. The Next.js example passes route locales into the server instance and adds a statically generated locale page with documentation.

Changes

Server locale rendering

Layer / File(s) Summary
Explicit locale resolution and tests
packages/react/src/createServerInstance.tsx, packages/react/src/createServerInstance.spec.tsx
getTolgee, getTranslate, and T accept optional locales. Tests cover resolver-based and explicit-locale behavior.
Next.js static locale integration
testapps/next-app-intl/src/app/[locale]/layout.tsx, testapps/next-app-intl/src/app/[locale]/ssg/page.tsx, testapps/next-app-intl/README.md
The localized layout passes its route locale to getTolgee. A locale-scoped static page and usage documentation are added.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Mergeability Score: ⚪ Minimal · up to d5d9e

The change adds explicit locale support for static server rendering while preserving existing behavior for callers without a locale, and the reported checks cover the affected package and SSG routes. No actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant StaticRoute
  participant LocaleLayout
  participant createServerInstance
  participant Tolgee
  StaticRoute->>LocaleLayout: provide locale route param
  LocaleLayout->>createServerInstance: call getTolgee({ locale })
  createServerInstance->>Tolgee: create or retrieve locale instance
  Tolgee-->>LocaleLayout: return configured instance
Loading

Possibly related PRs

  • tolgee/tolgee-js#3520: Both PRs modify the React T component’s typing or usage, but this PR adds locale forwarding.

Poem

A rabbit passes locale through the gate,
getTolgee now receives the route state.
Static pages bloom in every tongue,
While tested translations hop along.
The server knows the words to bring.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: explicit locale support for static server rendering in React.
Linked Issues check ✅ Passed The changes address issue #3526 by bypassing request locale resolution for explicit locales and documenting and testing static App Router rendering.
Out of Scope Changes check ✅ Passed All changes support explicit locale handling, regression coverage, static route validation, or usage guidance for issue #3526.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/react/src/createServerInstance.tsx (1)

38-41: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Support explicit locale in the Server <T> component.

Since getTranslate now supports an explicit locale to bypass getLocale() (and avoid request-bound headers() usage that breaks static generation), the Server <T> component will still fail during static generation because it calls getTranslate() without arguments.

Consider adding an optional locale prop to the server <T> component (e.g., by extending TProps or extracting it from the props) so users can safely use <T> in statically generated Server Components.

🤖 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 `@packages/react/src/createServerInstance.tsx` around lines 38 - 41, Add an
optional locale prop to the server T component’s props and pass it to
getTranslate, preserving the existing locale-resolution behavior when the prop
is omitted so static generation can bypass request-bound locale detection.
🤖 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.

Outside diff comments:
In `@packages/react/src/createServerInstance.tsx`:
- Around line 38-41: Add an optional locale prop to the server T component’s
props and pass it to getTranslate, preserving the existing locale-resolution
behavior when the prop is omitted so static generation can bypass request-bound
locale detection.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: afd64097-7f98-4935-9361-73c3ebb1deb4

📥 Commits

Reviewing files that changed from the base of the PR and between 322a726 and 7164155.

📒 Files selected for processing (5)
  • packages/react/src/createServerInstance.spec.tsx
  • packages/react/src/createServerInstance.tsx
  • testapps/next-app-intl/README.md
  • testapps/next-app-intl/src/app/[locale]/layout.tsx
  • testapps/next-app-intl/src/app/[locale]/ssg/page.tsx

@floze-the-genius
floze-the-genius force-pushed the fix/3526-static-app-router-locale branch from 4a96ccc to 9432a00 Compare August 9, 2026 13:53
@floze-the-genius

Copy link
Copy Markdown
Author

@Barush I refreshed the #3526 fix onto current main (70576b8); both original commits are exact by range-diff. The API remains additive, the React suite passes 38/38, and the production Next build emits all four locale routes as SSG pages. Snyk, CodeRabbit, build, ESLint, Prettier, and an independent API/SSG review are clean.

The GitHub Test workflow is waiting for fork approval here. Could you review when convenient?

const getTolgee = async () => {
const locale = await getLocale();
const tolgee = await getTolgeeInstance(locale);
const getTolgee = async (locale?: string) => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would pass the locale as prop of parameter object, so when we add more optional params in the future, it's no breaking change.

I would recommend the same for the other methods. :)

@floze-the-genius

Copy link
Copy Markdown
Author

Addressed the review in d5d9e43: getTolgee and getTranslate now take an optional { locale } parameter object, the server T path uses the same object form, and the test, README, and Next layout callers are updated consistently. Prettier, ESLint, @tolgee/react 39/39, generated public declarations, and the Next production build all pass; the example statically generates /en|cs|de|fr/ssg. CodeRabbit and Snyk are green. The refreshed Test workflow is action_required with zero jobs pending maintainer approval, not a code failure.

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.

App Router: TolgeeProvider (ssr) forces dynamic rendering — no SSG / generateStaticParams support

2 participants