Skip to content

Validate ICU branch keys where the macro is transformed - #80

Merged
k0d13 merged 2 commits into
mainfrom
kodie/icu-branch-key-validation
Aug 3, 2026
Merged

k0d13 merged 2 commits into
mainfrom
kodie/icu-branch-key-validation

Conversation

@k0d13

@k0d13 k0d13 commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Closes #54.

A select or plural branch key that is not a valid ICU key passed every stage of the toolchain and only failed when the runtime handed the pattern to @messageformat/parser. The constraint lives in that lexer, where a case is =\d+ or [^\p{Pat_Syn}\p{Pat_WS}]+ — and - is Pattern_Syntax, so an ordinary hyphenated string union ('sold-out') extracted to a normal-looking catalogue entry and then died with invalid syntax at line 2 col 3.

Validation now runs where the macro is transformed, while the key is still attached to a file and a line:

Invalid select branch key 'sold-out', an ICU key cannot contain punctuation or whitespace, try 'soldOut'
  • validateBranchIdentifier and getBranchCase live in @saykit/config, and convertMessageToIcu writes its cases through getBranchCase, so what is validated and what is emitted cannot drift.
  • Both parsers validate their collected branches. JSX attribute names accept hyphens too, so <Say.Select in-stock="…"> had the same hole.
  • The check is ICU's own rule rather than the stricter ASCII pattern used for placeholder names, so a key like año stays legal.

Numeric keys are the one adjacent case included: a number compiles to an exact-value case (=0), which only plural and ordinal accept, so say.select(x, { 0: … }) was failing at format time for the same reason. It now errors with the reason named.

The error is a plain Error, matching the existing Invalid placeholder name and say-tag validation — the filename comes from the bundler reporting which module threw. Naming the file and line in the message text would be a separate change across all three validators.

Docs get a paragraph under Select, and there are tests for the validator, both parsers, and both extractors.

Summary by CodeRabbit

  • Bug Fixes

    • Builds now catch invalid ICU branch keys earlier, rather than failing during message formatting.
    • Select, plural, and ordinal branches now validate punctuation, whitespace, numeric values, and unsupported exact-match cases.
    • Numeric plural and ordinal branches are converted to the correct ICU exact-value format.
  • Documentation

    • Added guidance on valid branch keys, including restrictions for select and numeric keys.
  • Tests

    • Expanded coverage for invalid keys, exact numeric matches, validation errors, and suggested corrections.

@changeset-bot

changeset-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 537dfd2

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

This PR includes changesets to release 10 packages
Name Type
@saykit/config Patch
@saykit/transform-js Patch
@saykit/transform-jsx Patch
saykit Patch
@saykit/carbon Patch
@saykit/react Patch
@saykit/format-json Patch
@saykit/format-po Patch
babel-plugin-saykit Patch
unplugin-saykit 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

@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
saykit Ready Ready Preview Aug 3, 2026 10:54pm

@github-actions github-actions Bot added tests Modifications, additions, or fixes related to testing package: config Related to @saykit/config and the CLI website Updates to the documentation website package: transform-js Related to @saykit/transform-js package: transform-jsx Related to @saykit/transform-jsx labels Aug 3, 2026
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@k0d13, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 54 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 63162a5a-fe1c-42b9-bb47-26c0896d9a2d

📥 Commits

Reviewing files that changed from the base of the PR and between 7f5137f and 537dfd2.

📒 Files selected for processing (3)
  • .changeset/hungry-pugs-repeat.md
  • packages/config/src/features/messages/identifier.test.ts
  • packages/config/src/features/messages/identifier.ts

Walkthrough

The change validates ICU branch keys during JavaScript and JSX transformation. It formats numeric plural and ordinal keys as ICU exact-value cases, rejects unsupported select keys, adds tests and documentation, and records patch releases.

Changes

ICU branch key handling

Layer / File(s) Summary
Branch identifier contract
packages/config/src/features/messages/identifier.ts, packages/config/src/features/messages/identifier.test.ts, packages/config/src/features/messages/convert.ts
The config package validates ICU branch identifiers, provides camel-case suggestions, and formats numeric keys as exact-value cases.
Parser validation
packages/transform-js/src/parser.ts, packages/transform-js/src/*test.ts, packages/transform-jsx/src/parser.ts, packages/transform-jsx/src/index.test.ts
The JavaScript and JSX parsers validate branch keys before creating choice messages. Tests cover invalid keys and numeric plural cases.
Documentation and release metadata
website/content/core-concepts/messages.mdx, .changeset/hungry-pugs-repeat.md
The documentation describes valid ICU branch keys. The changeset records patch releases for the affected packages.

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

Possibly related PRs

  • k0d13/saykit#66: Both changes update message identifier handling, but this change addresses ICU branch-key validation.

Poem

A rabbit checks each branch with care,
No hyphen hides inside the lair.
Numeric keys become =0,
Bad select keys must now say no.
Builds catch errors before runtime—
Hop, hop, an ICU-safe sign!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 clearly describes the main change: validating ICU branch keys during macro transformation.
Linked Issues check ✅ Passed The changes implement build-time validation for ICU branch keys during macro transformation, including errors and suggestions requested in issue #54.
Out of Scope Changes check ✅ Passed The code, tests, documentation, and changeset changes all support ICU branch-key validation and the linked issue objectives.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch kodie/icu-branch-key-validation

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.

@k0d13 k0d13 added the preview Publish a preview build and link it from the pull request label Aug 3, 2026

@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: 2

🤖 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 @.changeset/hungry-pugs-repeat.md:
- Line 7: Update the changeset entry to include ordinal branch keys alongside
select and plural branches, accurately documenting that the build now fails for
ICU-invalid ordinal keys before format time.

In `@packages/config/src/features/messages/identifier.ts`:
- Around line 21-23: Update getBranchCase in
packages/config/src/features/messages/identifier.ts:21-23 to apply exact-value
formatting only when the identifier string contains decimal digits, preserving
non-digit, whitespace-only, and signed numeric-like strings without coercing
them to =0 or another numeric case. Add regression tests covering empty,
whitespace-only, and signed numeric-like branch keys in
packages/config/src/features/messages/identifier.test.ts:187-232.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 37847bc3-353b-4aca-a58a-47bbae73b9cd

📥 Commits

Reviewing files that changed from the base of the PR and between 04b0e38 and 7f5137f.

📒 Files selected for processing (10)
  • .changeset/hungry-pugs-repeat.md
  • packages/config/src/features/messages/convert.ts
  • packages/config/src/features/messages/identifier.test.ts
  • packages/config/src/features/messages/identifier.ts
  • packages/transform-js/src/index.test.ts
  • packages/transform-js/src/parser.test.ts
  • packages/transform-js/src/parser.ts
  • packages/transform-jsx/src/index.test.ts
  • packages/transform-jsx/src/parser.ts
  • website/content/core-concepts/messages.mdx

Comment thread .changeset/hungry-pugs-repeat.md Outdated
Comment thread packages/config/src/features/messages/identifier.ts Outdated
@pkg-pr-new

pkg-pr-new Bot commented Aug 3, 2026

Copy link
Copy Markdown

Open in StackBlitz

@saykit/config

npm i https://pkg.pr.new/@saykit/config@80

@saykit/format-json

npm i https://pkg.pr.new/@saykit/format-json@80

@saykit/format-po

npm i https://pkg.pr.new/@saykit/format-po@80

saykit

npm i https://pkg.pr.new/saykit@80

@saykit/carbon

npm i https://pkg.pr.new/@saykit/carbon@80

@saykit/react

npm i https://pkg.pr.new/@saykit/react@80

babel-plugin-saykit

npm i https://pkg.pr.new/babel-plugin-saykit@80

unplugin-saykit

npm i https://pkg.pr.new/unplugin-saykit@80

@saykit/transform-js

npm i https://pkg.pr.new/@saykit/transform-js@80

@saykit/transform-jsx

npm i https://pkg.pr.new/@saykit/transform-jsx@80

commit: 7f5137f

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

The preview build of 7f5137f is published. Open it in the playground to run this pull request against your own code, straight from the browser.

@github-actions github-actions Bot removed the preview Publish a preview build and link it from the pull request label Aug 3, 2026
@k0d13
k0d13 merged commit 116496f into main Aug 3, 2026
24 checks passed
@k0d13
k0d13 deleted the kodie/icu-branch-key-validation branch August 3, 2026 22:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package: config Related to @saykit/config and the CLI package: transform-js Related to @saykit/transform-js package: transform-jsx Related to @saykit/transform-jsx tests Modifications, additions, or fixes related to testing website Updates to the documentation website

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ICU branch keys containing a hyphen fail at format time, not build time

1 participant