This might be somewhat related to #1453 . However, I believe this issue is worth fixing even in the current i18 version, at least in Japanese.
Motivation
The current Japanese translation in ja.ts embeds issue.expected and issue.received directly into messages. These values use programmer-oriented symbols defined in Valibot's core (e.g. >=3, !0, !"banned"), which is consistent with how the English default messages work.
However, when Japanese messages are displayed, those symbols appear inside natural Japanese sentences and feel deeply unnatural to Japanese speakers.
Example: what users actually see
The >=3 notation is arguably acceptable in English because it reads naturally as a mathematical expression in that context. In Japanese, however, embedding symbols like >=3 or !0 inside a Japanese sentence creates a jarring, unnatural reading experience that most Japanese speakers would find confusing.
minBytes(3) with input "a"
無効なバイト数: >=3 を期待しましたが、 1 を受け取りました
nonEmpty() with empty string
無効な長さ: !0 を期待しましたが、 0 を受け取りました
notValue("banned") with "banned"
無効な値: !"banned" を期待しましたが、 "banned" を受け取りました
end-user exposure
One might argue that Valibot error messages are only read by developers. This is true in many cases. For example, when inspecting API error responses during development.
However, there are common real-world scenarios where these messages are exposed directly to end users.
Frontend validation
// Valibot is used to validate form input on the client side
const result = v.safeParse(schema, formData);
if (!result.success) {
showToast(result.issues[0].message); // shown directly to the user
}
Backend validation with pass-through error responses
// Backend validates request body and returns issues as-is
const result = v.safeParse(schema, req.body);
if (!result.success) {
return res.status(400).json({ errors: result.issues.map(i => i.message) });
}
// Frontend displays these messages directly in the UI
In both cases, a message like 無効な長さ: !0 を期待しましたが、 0 を受け取りました would be shown to a general user. The expression !0 is not common in Japan, so many end users will not understand its meaning.
While developers can always override messages with setSpecificMessage, requiring them to redefine every validator message just to make them human-readable is a significant burden. I believe the content should be understandable to anyone, whether they are a programmer or a non-programmer end-user.
Proposal
The direct translation of en.ts into ja.ts sounds very unnatural to Japanese speakers due to cultural and grammatical differences.
Therefore, instead of simply using a direct translation of en.ts for ja.ts, how about revising the message to something that both programmers and average Japanese speakers can understand?
The approach is simple: don't embed issue.expected directly into the Japanese text. Instead, use issue.requirement (the actual constraint value). This alone will make the Japanese text sound overwhelmingly more natural.
min / max / gt / lt series
// Before
minBytes: (issue) => `無効なバイト数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`,
// After
minBytes: (issue) => `バイト数が不足しています: ${issue.requirement} バイト以上である必要がありますが、 ${issue.received} バイトを受け取りました`,
maxBytes: (issue) => `バイト数が超過しています: ${issue.requirement} バイト以下である必要がありますが、 ${issue.received} バイトを受け取りました`,
minLength: (issue) => `文字数が不足しています: ${issue.requirement} 文字以上である必要がありますが、 ${issue.received} 文字を受け取りました`,
maxLength: (issue) => `文字数が超過しています: ${issue.requirement} 文字以下である必要がありますが、 ${issue.received} 文字を受け取りました`,
minValue: (issue) => `値が小さすぎます: ${issue.requirement} 以上である必要がありますが、 ${issue.received} を受け取りました`,
maxValue: (issue) => `値が大きすぎます: ${issue.requirement} 以下である必要がありますが、 ${issue.received} を受け取りました`,
gtValue: (issue) => `値が小さすぎます: ${issue.requirement} より大きい値である必要がありますが、 ${issue.received} を受け取りました`,
ltValue: (issue) => `値が大きすぎます: ${issue.requirement} より小さい値である必要がありますが、 ${issue.received} を受け取りました`,
nonEmpty / empty series
// Before
nonEmpty: (issue) => `無効な長さ: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`,
// → "無効な長さ: !0 を期待しましたが、 0 を受け取りました"
// After...Very Simple!!
nonEmpty: (_issue) => `空にすることはできません`,
empty: (_issue) => `空である必要があります`,
not series
// Before
notBytes: (issue) => `無効なバイト数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`,
// → "無効なバイト数: !5 を期待しましたが、 5 を受け取りました"
// After
notBytes: (issue) => `無効なバイト数: ${issue.requirement} バイトは使用できません`,
notLength: (issue) => `無効な文字数: ${issue.requirement} 文字は使用できません`,
notGraphemes: (issue) => `無効な書記素数: ${issue.requirement} は使用できません`,
notEntries: (issue) => `無効な項目数: ${issue.requirement} 件は使用できません`,
notSize: (issue) => `無効なサイズ: ${issue.requirement} は使用できません`,
notWords: (issue) => `無効な単語数: ${issue.requirement} 単語は使用できません`,
notValue: (issue) => `使用できない値です: ${issue.requirement} は入力できません`,
notValues: (_issue) => `使用できない値が含まれています`,
This might be somewhat related to #1453 . However, I believe this issue is worth fixing even in the current i18 version, at least in Japanese.
Motivation
The current Japanese translation in
ja.tsembedsissue.expectedandissue.receiveddirectly into messages. These values use programmer-oriented symbols defined in Valibot's core (e.g.>=3,!0,!"banned"), which is consistent with how the English default messages work.However, when Japanese messages are displayed, those symbols appear inside natural Japanese sentences and feel deeply unnatural to Japanese speakers.
Example: what users actually see
The
>=3notation is arguably acceptable in English because it reads naturally as a mathematical expression in that context. In Japanese, however, embedding symbols like>=3or!0inside a Japanese sentence creates a jarring, unnatural reading experience that most Japanese speakers would find confusing.minBytes(3)with input"a"nonEmpty()with empty stringnotValue("banned")with"banned"end-user exposure
One might argue that Valibot error messages are only read by developers. This is true in many cases. For example, when inspecting API error responses during development.
However, there are common real-world scenarios where these messages are exposed directly to end users.
Frontend validation
Backend validation with pass-through error responses
In both cases, a message like
無効な長さ: !0 を期待しましたが、 0 を受け取りましたwould be shown to a general user. The expression!0is not common in Japan, so many end users will not understand its meaning.While developers can always override messages with
setSpecificMessage, requiring them to redefine every validator message just to make them human-readable is a significant burden. I believe the content should be understandable to anyone, whether they are a programmer or a non-programmer end-user.Proposal
The direct translation of
en.tsintoja.tssounds very unnatural to Japanese speakers due to cultural and grammatical differences.Therefore, instead of simply using a direct translation of
en.tsforja.ts, how about revising the message to something that both programmers and average Japanese speakers can understand?The approach is simple: don't embed
issue.expecteddirectly into the Japanese text. Instead, useissue.requirement(the actual constraint value). This alone will make the Japanese text sound overwhelmingly more natural.min/max/gt/ltseriesnonEmpty/emptyseriesnotseries