Skip to content

feat(i18n): add @clerk/i18n reactive i18n engine#8861

Open
alexcarpenter wants to merge 10 commits into
mainfrom
carp/i18n
Open

feat(i18n): add @clerk/i18n reactive i18n engine#8861
alexcarpenter wants to merge 10 commits into
mainfrom
carp/i18n

Conversation

@alexcarpenter

@alexcarpenter alexcarpenter commented Jun 15, 2026

Copy link
Copy Markdown
Member

Summary

Adds packages/i18n — a small, reactive i18n engine that will replace the current packages/localizations eager-merge approach. This PR establishes the foundations (engine only, no data, no migration). Integration with Clerk's UI components lives on the companion carp/i18n-mosaic branch.

What's in the package

  • createI18n($locale, { get }) — a namespace factory. Each i18n(namespace, base) call returns a nanostores computed store; the resolved Messages<B> type is inferred from base so call sites are fully typed with no codegen.
  • Message markersparams(template), count(forms), params(count(...)), messageFormat(template) — covering parameterised strings, plurals, combined plural+params, and rich-text markup with real React elements (no dangerouslySetInnerHTML).
  • Per-key fallbackoverride ?? locale ?? base. Locale data is fetched lazily; any missing key falls back to base individually, not the whole namespace.
  • Override layerdefineLocalization + a ReadableStore<ResolvedOverrides> passed to createI18n. Accepts nested ({ signIn: { title: '…' } }) or flat dot-notation ({ 'signIn.title': '…' }) forms, both fully typed against the base registry.
  • React bindingsuseStore (a stable useSyncExternalStore wrapper), <Message>, useMessage, formatToParts — in a separate @clerk/i18n/react entry point so the core is framework-free.
  • SSRallTasks() (nanostores built-in) flushes all in-flight locale loads globally; translationsLoading(i18n) / loadTranslations(store) scope the wait to one instance for per-request RSC rendering.
  • CImessagesToJSON(...stores) serialises each namespace's base back to raw JSON for upload to a translation service or diff-based change detection.

Why nanostores

The reactive core (computed, atom, task) is the only runtime dependency, and it was the right fit on every axis:

  • Size. nanostores is ~1 KB. The whole createI18n entry point budgets ≤ 2.2 kB; the React bindings ≤ 500 B excluding React. A full i18n engine at that weight isn't possible with heavier primitives.
  • computed eliminates manual invalidation. Each namespace store is a computed([$locale, $resolved, $overrides], …). When the locale changes or overrides update, all dependent stores re-derive automatically. The alternative — subscribing manually and calling set() — is error-prone and leaks subscriptions in SSR.
  • task() / allTasks() is built-in async coordination. Every locale fetch is registered as a nanostores task. allTasks() (already the SSR idiom for nanostores apps) resolves when all in-flight loads settle — zero plumbing on our side.
  • Framework-agnostic. The core has no React import; framework bindings are an optional entry point. The same store works in React, Vue, Svelte, or vanilla.
  • Precedent. @nanostores/i18n proved the pattern at production scale. We diverged purposefully (marker-based type inference, built-in override layer, messageFormat for rich text) but the reactive foundation is validated.

Architecture decisions

Decision Choice Rationale
Data in engine None — engine ships zero strings Bundle win; get(locale) is the seam between CDN-fetch and bundler chunk
Fallback granularity Per-key, not per-namespace Partial translations fall back gracefully without duplicating all-English namespaces
Override scope Locale-agnostic A brand override ("Sign in" → "Log in") should hold in every language
Rich text messageFormat + walk AST No dangerouslySetInnerHTML; React and string renderers share one recursive visitor
Flat vs nested overrides Both supported Nested for grouped authoring, flat for programmatic/JSON generation
React entry point Separate (/react) Core stays framework-free; tree-shaking removes React bindings from non-React consumers

What this is not

  • No migration of existing @clerk/localizations locale files (Phase 1–3, tracked separately).
  • No integration into @clerk/ui or @clerk/clerk-js (on carp/i18n-mosaic).
  • No CDN delivery mechanics for clerk-js (deferred to Phase 2).

Test plan

  • turbo test --filter @clerk/i18n — all unit + type tests green
  • turbo build --filter @clerk/i18n — ESM + CJS + .d.ts outputs clean
  • pnpm size --filter @clerk/i18ncreateI18n ≤ 2.2 kB, useStore + Message ≤ 500 B
  • Per-key fallback: locale missing key → English shown, locale has key → translated shown
  • Override beats locale beats base
  • messageFormat rich text renders real elements in the React binding test

Summary by CodeRabbit

  • New Features
    • Introduced the new @clerk/i18n reactive internationalization package with locale resolution, per-namespace message stores, async translation loading, and runtime localization overrides.
    • Added message formatting utilities (rich messageFormat, pluralization/count, params), plus serialization via messagesToJSON.
    • Included React integration (useStore, <Message />, useMessage) with SSR-friendly translation loading support.
  • Documentation
    • Added full @clerk/i18n package README.
  • Tests
    • Added unit, type-level, and React test coverage for locale selection, formatting, overrides, serialization, and typings.
  • Chores / Build
    • Added package manifest and build/test configuration for the i18n package.

@changeset-bot

changeset-bot Bot commented Jun 15, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b4e6475

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

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

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

@vercel

vercel Bot commented Jun 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
swingset Ready Ready Preview, Comment Jun 15, 2026 7:38pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
clerk-js-sandbox Skipped Skipped Jun 15, 2026 7:38pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 797decc5-e1fd-4f9d-8246-56bd62287d4e

📥 Commits

Reviewing files that changed from the base of the PR and between b428712 and 729027d.

📒 Files selected for processing (3)
  • packages/i18n/src/define-localization/index.test.ts
  • packages/i18n/src/define-localization/index.ts
  • packages/i18n/src/messages-to-json/index.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/i18n/src/messages-to-json/index.test.ts
  • packages/i18n/src/define-localization/index.ts
  • packages/i18n/src/define-localization/index.test.ts

📝 Walkthrough

Walkthrough

This PR introduces the @clerk/i18n package from scratch. It adds a nanostores-based reactive i18n system including core type definitions, message marker primitives (params, count, transform), an MF2-style message format pipeline, the createI18n store factory with async locale fetching and SSR support, override normalization via defineLocalization, a reactive Intl formatter, React integration hooks and components, and full package scaffolding with tests.

Changes

@clerk/i18n package

Layer / File(s) Summary
Core types and primitive marker factories
packages/i18n/src/types.ts, packages/i18n/src/atom/index.ts, packages/i18n/src/atom/index.test.ts, packages/i18n/src/browser/index.ts, packages/i18n/src/browser/index.test.ts, packages/i18n/src/locale-from/index.ts, packages/i18n/src/locale-from/index.test.ts, packages/i18n/src/count/index.ts, packages/i18n/src/count/index.test.ts, packages/i18n/src/params/index.ts, packages/i18n/src/params/index.test.ts, packages/i18n/src/transforms/index.ts, packages/i18n/src/transforms/index.test.ts
Defines all public TypeScript types (ReadableStore, WritableStore, plural forms, marker interfaces, override and registry types), the atom/localeFrom/browser locale utilities, and the count/params/transform message marker factories with their tests.
MF2-style message format pipeline
packages/i18n/src/message-format/index.ts, packages/i18n/src/message-format/index.test.ts
Implements the tokenizer (getMessageFormatParts), recursive walk visitor, messageFormat transform factory producing a callable RichText, and formatToParts serializer, with full test coverage including nested markup and edge cases.
createI18n reactive store factory
packages/i18n/src/create-i18n/index.ts, packages/i18n/src/create-i18n/index.test.ts
Defines CreateI18nOptions, MessageStore, and I18n; implements the factory including locale fetch de-duplication, SSR task() registration, $loading state, buildEntry marker dispatch for all marker types, buildMessages, and computed namespace stores with override merging. Extensive test coverage for overrides, failures, caching, and baseLocale.
SSR helpers, overrides, formatter, and messagesToJSON
packages/i18n/src/translations-loading/index.ts, packages/i18n/src/load-translations/index.ts, packages/i18n/src/define-localization/index.ts, packages/i18n/src/formatter/index.ts, packages/i18n/src/messages-to-json/index.ts, packages/i18n/src/translations-loading/index.test.ts, packages/i18n/src/load-translations/index.test.ts, packages/i18n/src/define-localization/index.test.ts, packages/i18n/src/formatter/index.test.ts, packages/i18n/src/messages-to-json/index.test.ts
Adds translationsLoading (subscribe-and-resolve on loading flag), loadTranslations (await in-flight then snapshot), defineLocalization (nested and flat dot-notation override normalization with prototype-pollution guards), reactive Intl-caching formatter factory, and messagesToJSON for serializing marker stores back to raw JSON.
React integration layer
packages/i18n/src/react/index.ts, packages/i18n/src/react/index.test.tsx
Adds useStore (built on useSyncExternalStore with SSR snapshot option and referentially stable callbacks), formatToReact (RichText-to-React-nodes with keyed Fragment markup folding), Message component, and useMessage memoized hook with tests covering StrictMode regression, markup nesting, and missing components.
Package scaffolding, barrel index, type tests, and docs
packages/i18n/package.json, packages/i18n/tsconfig.json, packages/i18n/tsconfig.test.json, packages/i18n/tsdown.config.mts, packages/i18n/vitest.config.mts, packages/i18n/vitest.setup.mts, packages/i18n/src/index.ts, packages/i18n/src/index.type.test.ts, packages/i18n/README.md, packages/i18n/.gitignore, .changeset/dull-badgers-start.md
Adds the full package manifest (dual ESM/CJS exports, scripts, deps), TypeScript build and test configs, tsdown build config, Vitest config with typecheck, the public barrel re-exporting all runtime values and types, compile-time type tests, README documentation, gitignore, and changeset.

Sequence Diagram(s)

sequenceDiagram
  participant App
  participant createI18n
  participant locale_atom as locale atom
  participant Fetcher as options.get
  participant MessageStore

  App->>createI18n: createI18n($locale, { get, overrides, cache })
  createI18n-->>App: i18n factory + i18n.loading
  App->>createI18n: i18n('namespace', baseMessages)
  createI18n-->>App: MessageStore (computed)
  locale_atom->>createI18n: locale changed to 'fr'
  createI18n->>Fetcher: get('fr') via task()
  createI18n->>MessageStore: loading = true
  Fetcher-->>createI18n: namespace data resolved
  createI18n->>MessageStore: merge overrides and rebuild entries
  createI18n->>MessageStore: loading = false
  MessageStore-->>App: updated messages snapshot
Loading
sequenceDiagram
  participant RSC as Server Component
  participant loadTranslations
  participant translationsLoading
  participant i18n_loading as i18n.loading

  RSC->>loadTranslations: loadTranslations(messages)
  loadTranslations->>translationsLoading: translationsLoading(messages.i18n)
  translationsLoading->>i18n_loading: subscribe until false
  i18n_loading-->>translationsLoading: loading becomes false
  translationsLoading-->>loadTranslations: resolved
  loadTranslations->>loadTranslations: messages.get()
  loadTranslations-->>RSC: translation snapshot
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

localizations, react

Suggested reviewers

  • wobsoriano
  • Ephem

Poem

🐇 A brand new package hops onto the scene,
@clerk/i18n, reactive and lean!
From params to count, with plural delight,
SSR tasks await, then render just right.
React hooks and stores, all wired in a row —
This bunny ships i18n, ready to go! 🌍

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(i18n): add @clerk/i18n reactive i18n engine' accurately summarizes the main change: introduction of a new i18n package with reactive capabilities built on nanostores.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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.

@github-actions github-actions Bot added the ui label Jun 15, 2026
New package: createI18n, params, count, messageFormat, defineLocalization,
loadTranslations, messagesToJSON, and React bindings (useStore, Message).
Built on nanostores; engine ships zero locale data.
Comment thread packages/i18n/src/messages-to-json/index.ts Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (2)
packages/i18n/src/define-localization/index.test.ts (1)

60-71: ⚡ Quick win

Add a regression test for dangerous keys (__proto__/constructor/prototype).

Current tests cover shape conversion well, but they don’t protect against prototype-polluting inputs. Add one malicious-key case so this behavior can’t regress.

🤖 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/i18n/src/define-localization/index.test.ts` around lines 60 - 71,
The test file for defineLocalization lacks regression coverage for prototype
pollution vulnerabilities. After the existing test `'passes non-string override
values through verbatim'`, add a new test case that verifies the
defineLocalization function properly handles dangerous keys like __proto__,
constructor, and prototype by ensuring these keys do not pollute the prototype
chain. The test should pass malicious-key inputs to defineLocalization and
assert that the resulting object structure does not exhibit prototype pollution
behavior (for example, verify that attempting to access inherited properties
through the polluted keys fails or returns undefined rather than contaminating
the prototype).
packages/i18n/src/messages-to-json/index.test.ts (1)

34-40: ⚡ Quick win

Add an edge-case test for __proto__ keys in namespace/message keys.

Given serialization writes dynamic keys, this suite should include a malicious-key case to prevent future prototype-pollution regressions.

🤖 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/i18n/src/messages-to-json/index.test.ts` around lines 34 - 40, Add a
new test case to the test suite in the messagesToJSON test file that covers the
edge-case for prototype pollution prevention. The test should invoke the
messagesToJSON function with `__proto__` as a key in either the namespace or
message objects, and verify that the function safely handles this malicious key
without causing prototype pollution or unintended side effects on the object
prototype chain.
🤖 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.

Inline comments:
In `@packages/i18n/package.json`:
- Around line 51-64: The pnpm-lock.yaml file is out of sync with the dependency
changes made in packages/i18n/package.json. Run pnpm install to regenerate the
lockfile with the updated specifiers for nanostores, `@testing-library/react`, and
other dependencies, then commit the updated pnpm-lock.yaml file to resolve the
CI blockage from the frozen-lockfile check.
- Around line 25-34: The `./react` subpath exports defined in package.json
(lines 25-34) are inconsistent with the documented contract which mentions
`formatToParts`, while the actual react entry point implementation only exposes
`useStore`, `Message`, `useMessage`, and `formatToReact`. Align the three
sources of truth: either update the react entry point implementation to export
`formatToParts` if that is the documented contract, or update the documentation
to accurately reflect what the react entry point actually exports (`useStore`,
`Message`, `useMessage`, `formatToReact`), ensuring all three align
consistently.

In `@packages/i18n/README.md`:
- Around line 1-5: Add a new "Compatibility" or "Compatibility Matrix" section
to the `@clerk/i18n` README.md that documents the supported versions for Node.js,
React, TypeScript, runtime environments, and any relevant package constraints.
This section should be added after the existing content to comply with the
coding guidelines that require maintaining compatibility matrices in package
READMEs, and should clearly specify which versions are supported and tested.

In `@packages/i18n/src/create-i18n/index.ts`:
- Around line 72-95: The issue is that Promise.resolve(get(locale)) evaluates
get(locale) synchronously, and if it throws synchronously, the attached catch()
and finally() handlers won't execute, leaving inFlight unredeemed and $loading
stuck at true. To fix this in the pending[locale] task function, replace
Promise.resolve(get(locale)) with Promise.resolve().then(() => get(locale)) to
defer the execution of get(locale) to the next microtask, ensuring that
synchronous errors are properly caught and the finally() handler always
decrements inFlight.
- Around line 78-80: The shallow merge performed by Object.assign({}, ...data)
on line 78 causes loss of translation keys when the same namespace appears in
multiple chunks of the data array. Replace the shallow merge logic with a deep
merge implementation that properly combines nested objects by namespace key,
ensuring that when multiple chunks contain the same namespace (like signIn),
their properties are merged together rather than one completely replacing the
other. The merged variable should contain all translation keys from all chunks
across their respective namespaces.

In `@packages/i18n/src/define-localization/index.ts`:
- Around line 28-37: This code is vulnerable to prototype pollution attacks
because unsanitized dynamic keys from user input are being written directly into
plain objects. At packages/i18n/src/define-localization/index.ts lines 28-37,
replace the for...in loop with Object.entries iteration, initialize the output
object and nested namespace objects using Object.create(null) to create
null-prototype maps, and validate both the namespace key and leaf key to reject
dangerous properties like __proto__, constructor, and prototype before any
assignment. At packages/i18n/src/messages-to-json/index.ts lines 42-46,
similarly replace the for...in loop with Object.entries or Object.keys
iteration, write into null-prototype maps created with Object.create(null), and
block the dangerous keys (__proto__, constructor, prototype) before assigning
values to prevent prototype pollution vulnerabilities in both locations.

In `@packages/i18n/src/index.ts`:
- Around line 1-45: The index.ts file in packages/i18n/src is functioning as a
barrel file with all re-exports, which violates the repository's guidelines
against barrel files due to circular dependency risks. Instead of maintaining a
single catch-all index.ts that re-exports everything (including all exports from
atom, browser, formatter, localeFrom, params, count, messageFormat, createI18n,
defineLocalization, loadTranslations, translationsLoading, messagesToJSON, and
their associated types), refactor to use explicit entry modules or narrowly
scoped export files. Consider creating separate entry points at the package root
level (e.g., packages/i18n/browser.ts, packages/i18n/formatter.ts, etc.) that
consumers can import from directly, or organize the current exports into
logical, narrowly-scoped files that group related functionality together rather
than aggregating everything in a single index.ts.

---

Nitpick comments:
In `@packages/i18n/src/define-localization/index.test.ts`:
- Around line 60-71: The test file for defineLocalization lacks regression
coverage for prototype pollution vulnerabilities. After the existing test
`'passes non-string override values through verbatim'`, add a new test case that
verifies the defineLocalization function properly handles dangerous keys like
__proto__, constructor, and prototype by ensuring these keys do not pollute the
prototype chain. The test should pass malicious-key inputs to defineLocalization
and assert that the resulting object structure does not exhibit prototype
pollution behavior (for example, verify that attempting to access inherited
properties through the polluted keys fails or returns undefined rather than
contaminating the prototype).

In `@packages/i18n/src/messages-to-json/index.test.ts`:
- Around line 34-40: Add a new test case to the test suite in the messagesToJSON
test file that covers the edge-case for prototype pollution prevention. The test
should invoke the messagesToJSON function with `__proto__` as a key in either
the namespace or message objects, and verify that the function safely handles
this malicious key without causing prototype pollution or unintended side
effects on the object prototype chain.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 7639b0ee-338a-4cc9-bc01-60f8ab0c9877

📥 Commits

Reviewing files that changed from the base of the PR and between ed2cf75 and d6f7327.

📒 Files selected for processing (39)
  • packages/i18n/.gitignore
  • packages/i18n/README.md
  • packages/i18n/package.json
  • packages/i18n/src/atom/index.test.ts
  • packages/i18n/src/atom/index.ts
  • packages/i18n/src/browser/index.test.ts
  • packages/i18n/src/browser/index.ts
  • packages/i18n/src/count/index.test.ts
  • packages/i18n/src/count/index.ts
  • packages/i18n/src/create-i18n/index.test.ts
  • packages/i18n/src/create-i18n/index.ts
  • packages/i18n/src/define-localization/index.test.ts
  • packages/i18n/src/define-localization/index.ts
  • packages/i18n/src/formatter/index.test.ts
  • packages/i18n/src/formatter/index.ts
  • packages/i18n/src/index.ts
  • packages/i18n/src/index.type.test.ts
  • packages/i18n/src/load-translations/index.test.ts
  • packages/i18n/src/load-translations/index.ts
  • packages/i18n/src/locale-from/index.test.ts
  • packages/i18n/src/locale-from/index.ts
  • packages/i18n/src/message-format/index.test.ts
  • packages/i18n/src/message-format/index.ts
  • packages/i18n/src/messages-to-json/index.test.ts
  • packages/i18n/src/messages-to-json/index.ts
  • packages/i18n/src/params/index.test.ts
  • packages/i18n/src/params/index.ts
  • packages/i18n/src/react/index.test.tsx
  • packages/i18n/src/react/index.ts
  • packages/i18n/src/transforms/index.test.ts
  • packages/i18n/src/transforms/index.ts
  • packages/i18n/src/translations-loading/index.test.ts
  • packages/i18n/src/translations-loading/index.ts
  • packages/i18n/src/types.ts
  • packages/i18n/tsconfig.json
  • packages/i18n/tsconfig.test.json
  • packages/i18n/tsdown.config.mts
  • packages/i18n/vitest.config.mts
  • packages/i18n/vitest.setup.mts

Comment thread packages/i18n/package.json
Comment thread packages/i18n/package.json
Comment thread packages/i18n/README.md
Comment thread packages/i18n/src/create-i18n/index.ts
Comment thread packages/i18n/src/create-i18n/index.ts Outdated
Comment thread packages/i18n/src/define-localization/index.ts Outdated
Comment thread packages/i18n/src/index.ts
@pkg-pr-new

pkg-pr-new Bot commented Jun 15, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@8861

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@8861

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@8861

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@8861

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@8861

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@8861

@clerk/express

npm i https://pkg.pr.new/@clerk/express@8861

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@8861

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@8861

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@8861

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@8861

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@8861

@clerk/react

npm i https://pkg.pr.new/@clerk/react@8861

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@8861

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@8861

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@8861

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@8861

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@8861

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@8861

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@8861

commit: 729027d

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@packages/i18n/package.json`:
- Line 4: The `private: true` property on line 4 of packages/i18n/package.json
prevents the package from being published to npm, which conflicts with the PR
objective of making `@clerk/i18n` a publishable package. Remove the `"private":
true,` line entirely from the package.json file, as having it set to true will
block all publishing attempts regardless of the publishConfig.access setting.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: b2b0f728-e690-4131-bc7f-3a3cac8b511d

📥 Commits

Reviewing files that changed from the base of the PR and between d6f7327 and fb90aba.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • packages/i18n/package.json
  • packages/i18n/src/messages-to-json/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/i18n/src/messages-to-json/index.ts

Comment thread packages/i18n/package.json
…space merge, prototype pollution

- Defer get(locale) to a microtask (Promise.resolve().then) so synchronous
  throws are caught by .catch() and inFlight/loading are always cleaned up
- Deep-merge NamespaceData chunks per namespace instead of Object.assign spread,
  so multiple chunks sharing a namespace key don't clobber each other
- Harden defineLocalization against prototype pollution: switch for...in to
  Object.keys, use Object.create(null) for output maps, and reject __proto__/
  constructor/prototype namespace and message keys
- Add regression tests for prototype-polluting inputs in defineLocalization and
  messagesToJSON
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants