trans_choice() 总返回单数是因为语言文件未用竖线分隔复数分支,如应写 'comment' => '1 条评论|:count 条评论' 而非普通键值对;非英语需显式调用 pluralizer::uselanguage() 设置对应语言规则。

直接用 trans_choice(),但必须配对语言文件里的竖线分隔格式,且非英语需显式设置 Pluralizer 语言 —— 否则多数情况会 fallback 到第一段或报错。
为什么 trans_choice() 总返回单数?
常见错误是语言文件里写了普通键值对,比如:'comment' => '1 条评论',没用竖线分隔复数分支。Laravel 的 trans_choice() 不解析语义,只按索引取竖线分隔后的第 N 段。
- 中文只需两段(1 和 其他),写成:
'comment' => '1 条评论|:count 条评论' - 英文也两段,但规则不同:
'comment' => '{0} No comments|{1} One comment|[2,*] :count comments'—— 这种 ICU 语法仅在@choice或 JSON 文件中生效,PHP 数组里不认大括号 - 若传入
$count = 0却仍显示“1 条评论”,说明语言文件没定义零值分支,或用了不支持零值的格式(如纯竖线分隔)
@choice 指令和 trans_choice() 有什么区别?
@choice 是 Blade 编译指令,底层调用 trans_choice(),但语法更严格:它强制要求语言文件中的值是 ICU 格式字符串(含 {0}、[2,*] 等),且只在 Blade 中可用。
- PHP 数组语言文件中,
@choice('messages.apples', $count)要求messages.php里是:'apples' => '{0} None|{1} One apple|[2,*] :count apples' - 而
trans_choice('messages.apples', $count)在 PHP 数组中只认竖线分隔,不解析 ICU 语法;想用 ICU,得换 JSON 语言文件或自定义解析器 - 两者都依赖
Pluralizer计算分支索引,所以非英语语言下不设Pluralizer::useLanguage('fr'),@choice也可能选错段
非英语语言(如法语、阿拉伯语)复数失效怎么办?
Laravel 默认 Pluralizer 只适配英语规则(1 → 单数,其余 → 复数)。法语有 2 种形式(1 vs 其他),阿拉伯语有 6 种 —— 不手动指定,trans_choice() 就永远只在第 0 和第 1 段之间切。
- 在
AppServiceProvider::boot()中加:Pluralizer::useLanguage('fr')(支持fr、es、ar等 30+ 语言代码) - 确保语言文件分支数匹配目标语言的复数类别数:法语只要两段,阿拉伯语要六段,少一段就会越界或 fallback 到空字符串
- 验证是否生效:临时 dump
Pluralizer::getPluralCategory(2, 'fr'),应返回other;若返回one,说明没设对语言或版本不兼容
JSON 语言文件里怎么写复数?
JSON 文件不支持嵌套数组,所以不能像 PHP 那样写 'comments' => ['{0}...', '{1}...', '[2,*]...']。它靠键名本身承载复数逻辑,且只接受 Laravel 兼容的 ICU 字符串作为值。
- 写法示例(
resources/lang/en.json):"There is one comment.|There are :count comments.": "There is one comment.|There are :count comments." - 调用时第一个参数必须是完整键名(即这个带竖线的字符串),不能只写
'comments'—— 因为 JSON 没命名空间概念 - 如果用 ICU 语法(如
{0} No comments|{1} One comment),必须确保Pluralizer已设对应语言,否则索引计算错误 - 注意:PHP 语言文件优先级高于 JSON,同目录下存在
en.php会覆盖en.json的同名键
最易被忽略的是:复数分支数量必须与目标语言的 Pluralizer 规则严格一致,不是“写越多越安全”。阿拉伯语写 3 段,第 4 个数字进来就无匹配项,结果为空。先查 Pluralizer::getPluralRules('ar') 返回的 category 列表,再决定写几段。











