Skip to content

Comments

fix: Use useTranslation() hook server-side for proper i18n SSR#639

Open
baptistegrimaud wants to merge 1 commit intomainfrom
fix-translations-server-side
Open

fix: Use useTranslation() hook server-side for proper i18n SSR#639
baptistegrimaud wants to merge 1 commit intomainfrom
fix-translations-server-side

Conversation

@baptistegrimaud
Copy link
Contributor

@baptistegrimaud baptistegrimaud commented Feb 19, 2026

Fixes #317.

Description

Use useTranslation() hook in server components: Replaced direct import { t } from "i18next" with usage of useTranslation() hook in all React server components (HelloWorld, LanguageSwitcher, etc.). This ensures translations are context-aware and avoid hydration mismatches between server and client.

Also, explicitly set the default namespace (defaultNS) in I18nextProvider wrapper to ensure proper translation loading for multiple modules on the same page. Its value is the bundle key (symbolic name).

Testing

Enhance the existing Cypress test with components from multiple JS modules on the same page, to validate:

  • 2 components from hydrogen module render server-side translations
  • 2 components from javascript-modules-engine-test-module render server-side translations
  • All client-side translations hydrate and update correctly

Tip

Documentation to guide the reviews: How to do a code review

@baptistegrimaud baptistegrimaud changed the title fix: Properly render i18n translations server-side fix: Use useTranslation() hook server-side for proper i18n SSR Feb 19, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses i18n conflicts when rendering multiple JavaScript modules on the same page by ensuring translations resolve against the correct module namespace during SSR and hydration (Issue #317).

Changes:

  • Replace direct t usage from the i18next singleton with useTranslation() in server-rendered React components (samples and template).
  • Set defaultNS on I18nextProvider during SSR (view renderer + islands) so useTranslation() defaults to the module bundle key namespace.
  • Extend the Cypress i18n E2E test to validate SSR + hydration behavior with components from two different modules on the same page.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/cypress/e2e/ui/testI18n.cy.ts Expands E2E coverage to assert SSR + hydrated translations for multiple modules on one page.
samples/hydrogen/src/components/LanguageSwitcher/default.server.tsx Switches server component translation usage to useTranslation() for context-aware SSR.
samples/hydrogen/src/components/HelloWorld/default.server.tsx Switches server component translation usage to useTranslation() for context-aware SSR.
javascript-modules-library/src/components/render/Island.tsx Provides defaultNS={bundleKey} to scope translations correctly within islands during SSR.
javascript-modules-engine/src/server/init-react.tsx Provides defaultNS={bundleKey} during SSR view rendering (and stops mutating global default namespace).
javascript-create-module/templates/hello-world/src/components/Hello/World/default.server.tsx Updates template server component to use useTranslation() to match the new SSR i18n approach.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +180 to +182
cy.get(
'p:contains("Welcome to Jahia! You successfully created a new JavaScript Module and a Jahia Website built with it. Here are a few things you can do now:")',
).should("have.length", 2);
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The SSR assertion for the Hydrogen component is coupled to the full English translation string via a p:contains("Welcome to Jahia! ...") selector. This will be brittle if the sample copy changes (even punctuation), causing unrelated i18n/SSR changes to fail the test. Consider selecting via a stable attribute (e.g., add a data-testid on the HelloWorld "welcome" paragraph) or assert on a smaller, intentionally stable substring.

Suggested change
cy.get(
'p:contains("Welcome to Jahia! You successfully created a new JavaScript Module and a Jahia Website built with it. Here are a few things you can do now:")',
).should("have.length", 2);
cy.get('p:contains("Welcome to Jahia!")').should("have.length", 2);

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

well, we're testing translations 🤷

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.

Multiple JS modules on the same page will create conflicting i18next instances

1 participant