Skip to content

fix(i18n): add missing async action translations - #1645

Merged
fabian-hiller merged 1 commit into
open-circle:mainfrom
MaxFreedomPollard:fix-i18n-async-actions
Sep 20, 2026
Merged

fabian-hiller merged 1 commit into
open-circle:mainfrom
MaxFreedomPollard:fix-i18n-async-actions

Conversation

@MaxFreedomPollard

@MaxFreedomPollard MaxFreedomPollard commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

@valibot/i18n never translates issues from partialCheckAsync, rawCheckAsync or rawTransformAsync. A pipeline that uses one of them reports the English default message while the sync twin in the same locale is translated.

import '@valibot/i18n/de';
import * as v from 'valibot';

const Sync = v.pipe(
  v.object({ password: v.string(), confirm: v.string() }),
  v.partialCheck([['password'], ['confirm']], (i) => i.password === i.confirm)
);

const Async = v.pipeAsync(
  v.objectAsync({ password: v.string(), confirm: v.string() }),
  v.partialCheckAsync([['password'], ['confirm']], async (i) => i.password === i.confirm)
);

const input = { password: 'a', confirm: 'b' };

v.safeParse(Sync, input, { lang: 'de' }).issues?.[0].message;
// 'Ungültige Eingabe: Object erhalten'

(await v.safeParseAsync(Async, input, { lang: 'de' })).issues?.[0].message;
// 'Invalid input: Received Object'

This hits anyone doing cross-field validation against a database or an API, which is the main reason to reach for partialCheckAsync in the first place. The form ends up with a mix of translated and untranslated messages.

Cause

_addIssue resolves a specific message by the action's own reference function, in library/src/utils/_addIssue/_addIssue.ts: getSpecificMessage(context.reference, issue.lang). An async action's reference is the async function itself, so library/src/actions/partialCheck/partialCheckAsync.ts sets reference: partialCheckAsync, not partialCheck, and rawCheck/rawCheckAsync.ts and rawTransform/rawTransformAsync.ts in the same folder layout do the same. The registrations come from Language['specific'] in packages/i18n/src/types.ts, which listed partialCheck, rawCheck and rawTransform with no Async siblings, so setSpecificMessage was never called for the three async references and the lookup always missed. check/checkAsync and checkItems/checkItemsAsync were already listed as separate keys, so this was the remaining gap rather than a design choice.

Comparing the 105 actions under library/src/actions that call _addIssue against the 102 keys in Language['specific'] leaves exactly partialCheckAsync, rawCheckAsync and rawTransformAsync, and nothing in the other direction.

Fix

The three keys are added to Language['specific'] and to all 34 locale files, each reusing the string already written for its sync twin, exactly as checkAsync and checkItemsAsync already do. No wording is invented and no existing message changes. kr.ts is untouched because it spreads ko. The generated packages/i18n/package.json and packages/i18n/jsr.json export maps gain the matching submodule entries in the position the build scripts emit them, which is the order of Object.entries(language.specific), so each new entry sits immediately after its sync twin in all 34 emitted languages and both files stay byte identical to their generated form. pnpm-lock.yaml, the build scripts and the library itself are not touched.

Tests

packages/i18n has no test runner and no job in .github/workflows/ci.yml (which covers library, packages/to-json-schema, website and the codemod), so nothing automated would have caught this and the guard here is the Language interface: dropping any one of the new keys from a single locale file is a tsc --noEmit error naming that file, which is what proves all 34 were updated. I also ran the repro above both ways against the locale data. Before the change the three async messages come back as Invalid input: Received Object and the sync one is translated. After it, all four return Ungültige Eingabe: Object erhalten.

Verification

tsc --noEmit over packages/i18n/src passes (the scripts half of that package's lint needs @types/node, which the scoped install does not pull, and nothing under scripts changed) and the diff is 1231 insertions with zero deletions across 38 files. pnpm test in library: 530 files, 4688 tests passed, no type errors. prettier --check on the changed files passes.

Summary by CodeRabbit

  • New Features
    • Added localized validation messages for asynchronous checks and transformations across 34 supported languages.
    • Added package exports for the asynchronous validation helpers, including both modern module and CommonJS usage.
  • Documentation
    • Updated the unreleased changelog to document the new localized messages.

`_addIssue` looks up a specific message by the action's own `reference`
function, and an async action's reference is the async function itself,
not its sync twin. `Language['specific']` listed `partialCheck`,
`rawCheck` and `rawTransform` but none of their `Async` counterparts, so
no locale ever registered a message for them and `partialCheckAsync`,
`rawCheckAsync` and `rawTransformAsync` fell back to the English default
while the sync twin in the same pipeline was translated. Each new key
reuses the string already written for its sync twin, which is how
`checkAsync` and `checkItemsAsync` are handled, so no new wording is
introduced. The generated `package.json` and `jsr.json` export maps gain
the matching submodule entries.
@coderabbitai

coderabbitai Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 02c951ba-5780-4cdd-8649-e54054bc8b71

📥 Commits

Reviewing files that changed from the base of the PR and between 1bb74b0 and d1c4334.

📒 Files selected for processing (38)
  • packages/i18n/CHANGELOG.md
  • packages/i18n/jsr.json
  • packages/i18n/package.json
  • packages/i18n/src/ar.ts
  • packages/i18n/src/az.ts
  • packages/i18n/src/ca.ts
  • packages/i18n/src/cs.ts
  • packages/i18n/src/de.ts
  • packages/i18n/src/el.ts
  • packages/i18n/src/en.ts
  • packages/i18n/src/es.ts
  • packages/i18n/src/fa.ts
  • packages/i18n/src/fi.ts
  • packages/i18n/src/fr.ts
  • packages/i18n/src/hu.ts
  • packages/i18n/src/id.ts
  • packages/i18n/src/it.ts
  • packages/i18n/src/ja.ts
  • packages/i18n/src/ko.ts
  • packages/i18n/src/mn.ts
  • packages/i18n/src/nb.ts
  • packages/i18n/src/nl.ts
  • packages/i18n/src/nn.ts
  • packages/i18n/src/pl.ts
  • packages/i18n/src/pt.ts
  • packages/i18n/src/ro.ts
  • packages/i18n/src/ru.ts
  • packages/i18n/src/rw.ts
  • packages/i18n/src/sk.ts
  • packages/i18n/src/sl.ts
  • packages/i18n/src/sv.ts
  • packages/i18n/src/tr.ts
  • packages/i18n/src/types.ts
  • packages/i18n/src/uk.ts
  • packages/i18n/src/uz.ts
  • packages/i18n/src/vi.ts
  • packages/i18n/src/zh-CN.ts
  • packages/i18n/src/zh-TW.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


Walkthrough

The i18n package adds localized messages for partialCheckAsync, rawCheckAsync, and rawTransformAsync across its locale catalogs. The Language.specific type includes the new async message fields. JSR and npm export maps expose the three async subpaths for all supported locales. The changelog records the translation additions.

Suggested reviewers: fabian-hiller

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to d1c43

The async validation translations and locale export paths are consistently added with no actionable current-head issue identified.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding missing asynchronous action translations to i18n.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3…
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.

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.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 38 files

Re-trigger cubic

@pkg-pr-new

pkg-pr-new Bot commented Sep 15, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/valibot@1645

commit: d1c4334

@yslpn yslpn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, it seems we've lost that. Thank you!

@fabian-hiller

Copy link
Copy Markdown
Member

Thank you!

@fabian-hiller
fabian-hiller merged commit 78682df into open-circle:main Sep 20, 2026
17 checks passed
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.

3 participants