fix: standardize i18n pluralization to two-part format (#9371)

## Summary

- Converts redundant three-part pluralization patterns (`zero | singular
| plural`) to standard two-part format (`singular | plural`) across 11
locale files
- Only converts patterns where the zero form duplicates the singular or
plural form
- Retains three-part patterns where the zero form provides distinct
content (e.g. `"No items selected"`) or where the language
linguistically requires all three forms (Russian singular/paucal/plural)

## Context

Vue i18n selects plural forms based on the number of choices:

**3-part** `"{count} nodes | {count} node | {count} nodes"`:
| count | index | result |
|-------|-------|--------|
| 0 | 0 (zero) | "0 nodes" |
| 1 | 1 (singular) | "1 node" |
| 2+ | 2 (plural) | "N nodes" |

**2-part** `"{count} node | {count} nodes"`:
| count | index | result |
|-------|-------|--------|
| 0 | 1 (plural) | "0 nodes" |
| 1 | 0 (singular) | "1 node" |
| 2+ | 1 (plural) | "N nodes" |

Output is identical — the zero form was always a duplicate of the plural
form. This PR removes that redundancy.

## Changes

| Locale | Keys changed |
|--------|-------------|
| en, es, fr, pt-BR, ar, tr | 5 (`nodesCount`, `asset`, `errorCount`,
`downloadsFailed`, `exportFailed`) |
| ja, ko, fa | 3 (`asset`, `nodesCount`, `downloadsFailed`) |
| ru | 2 (`downloadsFailed`, `exportFailed`) |
| zh-TW | 2 (`nodesCount`, `downloadsFailed`) |

## Test plan

- [ ] Verify pluralization renders correctly for count=0, count=1,
count=2+ in affected UI areas
- [ ] Spot-check non-English locales (especially Russian which retains
3-part for linguistically distinct forms)

- Fixes #9277

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
This commit is contained in:
Dante
2026-03-13 10:16:59 +09:00
committed by GitHub
parent d82bce90ea
commit 649b9b3fe3
9 changed files with 36 additions and 36 deletions

View File

@@ -862,7 +862,7 @@
"promptExecutionError": "فشل تنفيذ الطلب"
},
"errorOverlay": {
"errorCount": "{count} أخطاء | {count} خطأ | {count} أخطاء",
"errorCount": "{count} خطأ | {count} أخطاء",
"seeErrors": "عرض الأخطاء"
},
"essentials": {
@@ -909,7 +909,7 @@
"downloadFailed": "فشل تحميل \"{name}\"",
"exportCompleted": "تحميل ZIP جاهز",
"exportError": "فشل التصدير",
"exportFailed": "{count} فشل في التصدير | {count} فشل في التصدير | {count} عمليات تصدير فشلت",
"exportFailed": "{count} فشل في التصدير | {count} عمليات تصدير فشلت",
"exportFailedSingle": "فشل إنشاء تصدير ZIP",
"exportStarted": "يتم تجهيز تحميل ZIP...",
"exportingAssets": "جاري تصدير العناصر",
@@ -928,7 +928,7 @@
"amount": "الكمية",
"apply": "تطبيق",
"architecture": "الهندسة المعمارية",
"asset": "{count} أصل | {count} أصل | {count} أصول",
"asset": "{count} أصل | {count} أصول",
"audioFailedToLoad": "فشل تحميل الصوت",
"audioProgress": "تقدم الصوت",
"author": "المؤلف",
@@ -1114,7 +1114,7 @@
"nodeSlotsError": "خطأ في فتحات العقدة",
"nodeWidgetsError": "خطأ في عناصر واجهة العقدة",
"nodes": "العُقَد",
"nodesCount": "{count} عقدة | {count} عقدة | {count} عقدة",
"nodesCount": "{count} عقدة | {count} عقدة",
"nodesRunning": "العُقَد قيد التشغيل",
"none": "لا شيء",
"nothingToCopy": "لا يوجد ما يمكن نسخه",
@@ -2295,7 +2295,7 @@
"progressToast": {
"allDownloadsCompleted": "اكتملت جميع التنزيلات",
"downloadingModel": "جاري تنزيل النموذج...",
"downloadsFailed": "{count} فشل في التنزيل | {count} فشل في التنزيل | {count} فشل في التنزيل",
"downloadsFailed": "{count} فشل في التنزيل | {count} فشل في التنزيل",
"failed": "فشل",
"filter": {
"all": "الكل",