Skip to content

feat: add i18n support with next-intl for Spanish translation#1670

Open
Davydl wants to merge 4 commits intorecoupable:mainfrom
Davydl:main
Open

feat: add i18n support with next-intl for Spanish translation#1670
Davydl wants to merge 4 commits intorecoupable:mainfrom
Davydl:main

Conversation

@Davydl
Copy link
Copy Markdown

@Davydl Davydl commented Apr 13, 2026

What

Adds internationalization (i18n) support using next-intl library.

Changes

  • Installed next-intl
  • Created messages/en.json and messages/es.json
  • Updated OfflinePage.tsx to use translations
  • Added i18n/request.ts configuration
  • Updated next.config.mjs

Why

The app is currently English-only. This PR sets up the foundation
for Spanish translation, starting with OfflinePage as a proof of concept.


Summary by cubic

Adds i18n with next-intl and ships a Spanish locale, defaulting to English. OfflinePage now shows translated text based on the active locale.

  • New Features

    • Added i18n/request.ts to load messages per request.
    • Added messages/en.json and messages/es.json.
    • Updated OfflinePage.tsx to use useTranslations("OfflinePage").
    • Integrated the next-intl plugin in next.config.mjs (wrapped with next-pwa).
  • Bug Fixes

    • Corrected the messages import path in i18n/request.ts.
    • Switched to next-intl v4 API using params.requestLocale with an en fallback.
    • Validated requested locale against a supported list before dynamic import to prevent invalid paths.

Written for commit b443d35. Summary will update on new commits.

Summary by CodeRabbit

  • New Features
    • Offline page now supports multiple languages with localized content for title, description, and error resolution messaging.

@Davydl Davydl requested a review from sweetmantech as a code owner April 13, 2026 22:08
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 13, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • i18n/request.ts is excluded by none and included by none

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 97735615-49a1-472f-91bf-fb94ac71d31a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The OfflinePage component was updated to support internationalization by integrating the next-intl library. Static text strings in the heading, description, and resolution messaging were replaced with localized translation keys, enabling multilingual content delivery without modifying the component's structure or logic.

Changes

Cohort / File(s) Summary
Internationalization Integration
components/OfflinePage.tsx
Added useTranslations hook from next-intl and scoped translator to "OfflinePage". Replaced static text strings (<h1> and <p> content) with localized keys: t("title"), t("description"), and t("resolution"). No structural changes to component or export signatures.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🌍 Static strings now speak in tongues,
A translator's touch, i18n begun,
One component learns to cross the sea—
OfflinePage, now globally free! ✨

🚥 Pre-merge checks | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Solid & Clean Code ⚠️ Warning OfflinePage component lacks required 'use client' directive for useTranslations hook and missing TypeScript Props interface pattern established in codebase. Add 'use client' directive at top of file and create Props interface following ErrorPageLayout pattern for type safety and runtime correctness.

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

✨ 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 and usage tips.

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Apr 13, 2026

Someone is attempting to deploy a commit to the Recoupable Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1c2ad0252a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread i18n/request.ts Outdated
import { getRequestConfig } from "next-intl/server";

export default getRequestConfig(async ({ locale }) => ({
messages: (await import(`./messages/${locale}.json`)).default,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Load translation files from correct directory

getRequestConfig imports messages from ./messages/${locale}.json, which resolves relative to i18n/request.ts (i.e. i18n/messages/...), but this commit adds locale files under /messages at repo root. As a result, resolving translations will fail with module-not-found when this config runs (e.g., opening the offline page with translations), so i18n is broken until the path is corrected (or files are moved).

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@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)
components/OfflinePage.tsx (1)

22-26: Prefer semantic text blocks over <br /> in localized content.

Using <br /> to split two translatable messages constrains layout per locale. Render them as separate paragraphs for better semantics and translation flexibility.

♻️ Suggested refactor
-        <p className="text-muted-foreground max-w-md mx-auto text-base md:text-lg">
-          {t("description")}
-          <br />
-          {t("resolution")}
-        </p>
+        <div className="text-muted-foreground max-w-md mx-auto text-base md:text-lg">
+          <p>{t("description")}</p>
+          <p className="mt-2">{t("resolution")}</p>
+        </div>

As per coding guidelines, "Use semantic HTML elements appropriate to the component's role" and "Start with semantic HTML first, then augment with ARIA if needed".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/OfflinePage.tsx` around lines 22 - 26, In OfflinePage.tsx replace
the single paragraph that uses a <br /> between two translated strings with two
semantic text blocks (e.g., two <p> elements or separate elements inside the
existing container) so each translation key t("description") and t("resolution")
is rendered independently; update the JSX around the element with className
"text-muted-foreground max-w-md mx-auto text-base md:text-lg" to contain two
semantic blocks to allow translators/layouts full control and preserve existing
styling by applying the same className or container styles as needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@components/OfflinePage.tsx`:
- Around line 22-26: In OfflinePage.tsx replace the single paragraph that uses a
<br /> between two translated strings with two semantic text blocks (e.g., two
<p> elements or separate elements inside the existing container) so each
translation key t("description") and t("resolution") is rendered independently;
update the JSX around the element with className "text-muted-foreground max-w-md
mx-auto text-base md:text-lg" to contain two semantic blocks to allow
translators/layouts full control and preserve existing styling by applying the
same className or container styles as needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6d75baf3-bb8a-4362-adbb-da1b0af56c6f

📥 Commits

Reviewing files that changed from the base of the PR and between 4dad450 and 1c2ad02.

⛔ Files ignored due to path filters (6)
  • i18n/request.ts is excluded by none and included by none
  • messages/en.json is excluded by none and included by none
  • messages/es.json is excluded by none and included by none
  • next.config.mjs is excluded by none and included by none
  • package.json is excluded by none and included by none
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml and included by none
📒 Files selected for processing (1)
  • components/OfflinePage.tsx

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.

2 issues found across 7 files

Confidence score: 2/5

  • High-confidence, high-severity issues in i18n/request.ts indicate a likely runtime break in locale message loading, so merge risk is elevated.
  • The import path ./messages/${locale}.json appears incorrect for the current project layout, which can cause module resolution failures when loading translations.
  • The next-intl v4 callback uses requestLocale (Promise), so destructuring locale likely yields undefined and makes the dynamic import fail for all locales.
  • Pay close attention to i18n/request.ts - fix callback parameter handling and message import path to restore i18n loading behavior.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="i18n/request.ts">

<violation number="1" location="i18n/request.ts:3">
P1: In next-intl v4, the callback parameter is `requestLocale` (a `Promise`), not `locale`. Destructuring `locale` here gives `undefined`, so the dynamic import will always fail.</violation>

<violation number="2" location="i18n/request.ts:4">
P1: Custom agent: **Flag AI Slop and Fabricated Changes**

Incorrect relative import path — `./messages/${locale}.json` resolves to `i18n/messages/${locale}.json`, but the message files are at the project root (`messages/en.json`, `messages/es.json`). This will fail at runtime. Use `../messages/${locale}.json` instead.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread i18n/request.ts Outdated
Comment thread i18n/request.ts Outdated
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.

0 issues found across 1 file (changes from recent commits).

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

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.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="i18n/request.ts">

<violation number="1" location="i18n/request.ts:5">
P1: Validate `locale` against the supported set before using it in the dynamic import. If an unsupported locale slips through (e.g. `"fr"`), the `import()` will throw an unhandled `MODULE_NOT_FOUND` error at runtime.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread i18n/request.ts
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.

0 issues found across 1 file (changes from recent commits).

Requires human review: This PR introduces an architectural change by adding i18n support, including a new production dependency and modifications to the global next.config.mjs.

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