Skip to content

chore: implement i18next#210

Open
camrun91 wants to merge 10 commits intomainfrom
YPE-1957-react-sdk-implement-i-18-next
Open

chore: implement i18next#210
camrun91 wants to merge 10 commits intomainfrom
YPE-1957-react-sdk-implement-i-18-next

Conversation

@camrun91
Copy link
Copy Markdown
Collaborator

@camrun91 camrun91 commented Apr 8, 2026

This PR puts i18next into place and sets up a single translation string to show how it will work.

The current implementation is to mark i18next as a peer dependency and make it required. This is to prevent conflicts with any implementation apps having their own i18next implementation.

Greptile Summary

This PR wires up i18next to the @youversion/platform-react-ui package using an isolated instance (createInstance()) so the SDK's translations can never collide with a host app's own i18next configuration. The only translated surface right now is the "Verse of The Day" label in VerseOfTheDay. Previous concerns (unified versioning, silent init failure, SSR-breaking LanguageDetector, and the optional: true / static-import contradiction) have all been addressed in this revision.

Confidence Score: 5/5

Safe to merge — all previously raised blockers are resolved; only two minor P2 suggestions remain.

Unified versioning is now correct (all three packages bumped), the LanguageDetector SSR risk is gone, init errors are observable via .catch(), and the isolated-instance design is intentional and coherent. The remaining findings are P2: a changeset description that mischaracterises the deps as 'optional peer dependencies' and a missing explicit lng that may produce a dev-mode warning. Neither blocks correctness.

The changeset description in .changeset/add-i18next-support.md should be corrected before merge to avoid misleading changelog consumers.

Vulnerabilities

No security concerns identified. i18next resources are in-memory constants, no user-supplied input reaches the translation layer, and escapeValue: false is safe because React's JSX already escapes all output.

Important Files Changed

Filename Overview
.changeset/add-i18next-support.md Changeset now correctly bumps all three packages (unified versioning addressed), but the description inaccurately calls i18next/react-i18next 'optional peer dependencies' when they are regular bundled deps.
packages/ui/src/i18n/index.ts Isolated i18next instance via createInstance() with .catch() error handler; LanguageDetector removed (SSR-safe); no explicit lng may produce a dev-mode warning.
packages/ui/package.json i18next and react-i18next added as regular dependencies (bundled isolated instance approach, consistent with tsup config); no peerDependenciesMeta or optional markers.
packages/ui/src/components/verse-of-the-day.tsx useTranslation correctly pinned to SDK's isolated i18n instance via { i18n } option; replaces hardcoded string with t('verseOfTheDay').
packages/ui/src/i18n/locales/en.json Single translation key for 'Verse of The Day' in English locale; clean baseline for future strings.
.gitignore Added .omc/ to the ignore list; straightforward tooling artifact exclusion.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["packages/ui/src/i18n/index.ts\n(module load)"] -->|"createInstance()"| B["Isolated i18n instance"]
    B -->|"use(initReactI18next)\n.init({ resources })"| C["In-memory EN resources loaded"]
    C --> D["i18n instance exported"]
    D --> E["verse-of-the-day.tsx\nimport i18n from '@/i18n'"]
    E -->|"useTranslation(undefined, { i18n })"| F["t() bound to SDK instance"]
    F -->|"t('verseOfTheDay')"| G["'Verse of The Day'"]
    H["Host app's i18next instance"] -.->|"Completely isolated\nno interference"| B
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: .changeset/add-i18next-support.md
Line: 7

Comment:
**Changeset description doesn't match the implementation**

The description states "i18next and react-i18next are optional peer dependencies", but in `packages/ui/package.json` both are listed under regular `dependencies`, not `peerDependencies`. They will be **bundled** into the SDK output (they're also absent from tsup's `external` array). A consumer who reads the changelog may incorrectly assume they don't need to install either package themselves, or that they can omit them without consequence.

The description should reflect the actual approach — isolated bundled instance — so consumers understand the bundle size tradeoff and don't expect to supply their own copies.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: packages/ui/src/i18n/index.ts
Line: 15-22

Comment:
**No explicit `lng` — i18next may emit a console warning in dev**

Without an explicit `lng` and no language-detector plugin, i18next v26 internally sets the language to `undefined` and falls back to `fallbackLng`. In development mode this can produce a warning like "i18next: init: no language detected". Since the SDK only ships English strings, setting `lng: 'en'` explicitly makes the intent clear, silences any warning, and prevents any edge-case where a future i18next version changes detection behaviour.

```suggestion
  .init({
    resources,
    lng: 'en',
    defaultNS,
    fallbackLng: 'en',
    interpolation: {
      escapeValue: false, // React already escapes
    },
  })
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (10): Last reviewed commit: "fix: internalize i18next" | Re-trigger Greptile

Context used:

  • Rule used - Unified versioning: All packages must maintain exa... (source)

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 8, 2026

🦋 Changeset detected

Latest commit: c524bb1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@youversion/platform-core Minor
@youversion/platform-react-ui Minor
@youversion/platform-react-hooks Minor
vite-react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 8, 2026

Greptile Summary

This PR introduces i18next support in @youversion/platform-react-ui by creating an isolated i18n instance for the VerseOfTheDay component label, with one English translation string as the initial use case. All previously-flagged blocking concerns have been addressed: unified versioning now bumps all three packages, LanguageDetector is removed (SSR-safe), init errors are caught and logged, i18next/react-i18next are correctly in peerDependencies (non-optional) and externalized in tsup.

Confidence Score: 5/5

Safe to merge — all P0/P1 concerns from prior rounds are resolved; only a minor devDependencies convention suggestion remains.

All previously-flagged blocking issues (unified versioning, SSR safety, silent init failure, optional peer deps, tsup externalization) are addressed. The one remaining finding (peer deps not mirrored in devDependencies) is P2 and does not affect correctness in the current pnpm workspace setup.

packages/ui/package.json — minor devDependencies convention note only.

Vulnerabilities

No security concerns identified. The i18n implementation uses in-memory resources only (no external fetches), the isolated instance avoids global state mutation, and no user input flows through the translation layer.

Important Files Changed

Filename Overview
.changeset/add-i18next-support.md Correctly bumps all three packages (core, react-ui, react-hooks) together, resolving the unified-versioning concern from the previous review round.
packages/ui/package.json i18next and react-i18next correctly moved to peerDependencies (non-optional); they are absent from devDependencies, relying on pnpm's auto-install-peers behaviour to make them available locally.
packages/ui/src/i18n/index.ts Uses createInstance() for isolation, removes LanguageDetector (SSR-safe), adds .catch() for error visibility — all previous concerns addressed.
packages/ui/src/components/verse-of-the-day.tsx Passes the SDK's isolated i18n instance directly to useTranslation, bypassing the host app's provider — intentional design choice consistent with the isolated instance approach.
packages/ui/tsup.config.ts i18next and react-i18next added to external array, ensuring they are not bundled and the peer-dep contract is honoured.
packages/ui/src/i18n/locales/en.json Single English translation key added; straightforward.
.gitignore Adds .omc/ to gitignore — trivial housekeeping.
pnpm-lock.yaml Lock file updated to reflect resolution of i18next@26.0.4 and react-i18next@17.0.2 as peer dependencies; no unexpected dependency changes.

Sequence Diagram

sequenceDiagram
    participant App as Consumer App
    participant VOTD as VerseOfTheDay
    participant i18n as src/i18n/index.ts
    participant i18next as i18next (peer)
    participant react_i18next as react-i18next (peer)

    Note over i18n: Module load (singleton, isolated instance)
    i18n->>i18next: createInstance()
    i18n->>react_i18next: .use(initReactI18next)
    i18n->>i18n: .init({ resources: {en}, fallbackLng: 'en' }).catch(...)

    App->>VOTD: render VerseOfTheDay
    VOTD->>react_i18next: useTranslation(undefined, { i18n })
    react_i18next-->>VOTD: t()
    VOTD->>i18n: t('verseOfTheDay')
    i18n-->>VOTD: "Verse of The Day"
Loading

Reviews (9): Last reviewed commit: "fix: make i18next required" | Re-trigger Greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 8, 2026

Tip:

Greploops — Automatically fix all review issues by running /greploops in Claude Code. It iterates: fix, push, re-review, repeat until 5/5 confidence.

Use the Greptile plugin for Claude Code to query reviews, search comments, and manage custom context directly from your terminal.

@camrun91 camrun91 marked this pull request as draft April 8, 2026 17:57
@camrun91 camrun91 marked this pull request as ready for review April 8, 2026 20:00
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Signed-off-by: Cameron Llewellyn <cameron.b.llewellyn@gmail.com>
Copy link
Copy Markdown
Collaborator

@bmanquen bmanquen left a comment

Choose a reason for hiding this comment

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

Looks good just one comment for clarification/learning.

@camrun91
Copy link
Copy Markdown
Collaborator Author

@bmanquen I am going to wait and let @cameronapak take a look at this too and make sure it tracks with what he thinks is best.

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.

2 participants