From 05dca6213a6cdf22c113b76aa91c8f8518c5414f Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Mon, 28 Sep 2026 17:12:41 +0000 Subject: [PATCH] check:i18n-parity fails on a Traditional-only character in the zh catalogue The character set (322, from the UPG-100 owner's census, minus two shared by both scripts) is a floor, and the PASS line says so; a t2s converter would make it exact if one is ever installed. --- internal/check-i18n-parity.mjs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/internal/check-i18n-parity.mjs b/internal/check-i18n-parity.mjs index 124043e40..2a2ffa18f 100644 --- a/internal/check-i18n-parity.mjs +++ b/internal/check-i18n-parity.mjs @@ -117,4 +117,24 @@ if (improved.length) { for (const i of improved) console.log(' ' + i) } const debt = rows.reduce((a, r) => a + r.missing, 0) +// ★ zh IS SIMPLIFIED, and a Traditional string in it renders mixed scripts in one row (buttons.json +// once had 禱告名單 beside 为他们祷告). This arm fails on any zh value containing a character that +// exists ONLY in Traditional. The list is a FLOOR, not a converter: a Traditional character missing +// from it passes unseen, so the PASS line says "from a known set", never "none remain". No converter +// (opencc) is installed; if one is added, replace this with a t2s round-trip. +const TRAD_ONLY = new Set([...'來個們價兒動務區問單國圖學實寫將對層師帶幣廠廣廳愛應懷戰戲擊據擴擺攝敵數斷時曬書會東條棄業樂樓標樣樹橋機歷歸殺毀氣滅漢潔濟為無燈營爭爾獨獲現瑪環產畫異當疊發盡監禮禱種稱積穩窮竊競筆節範簡籃籌粵糧紀約紅納純紙級細終組結絕絡給統絲經綠維網緊線緣編緩縣縮總績織繼續罰羅義習聯聰聲職聽肅腦臟與興舉舊華萬藝藥蘇蘭蟲衆術衛製複見規視親覺觀訂計訊討訓記訪設許診註評詞詢試詩話該詳誌認語誠誤說誰課調談請論諸講謝謹證識譜譯議護讀變讓讚豐貓財貧貨貪責貴買費賀資賊賓賜賞賢賣賤質購贊贏赴趕車軌軍軟載輕輛輪轉辦辭農這運過達違遠適遲遷選還邊鄉鄰醫釋針銀鋪鋼錢鍵鎖鐘鐵長門閉開閱闆闊關陣陳陽隊階雙雜雞離難雲電霧靈靜韓頁項順預頓領頭頻顆題顏願類顧顯風飄飛養餘館馬驗體魚鳥麼點']) +const zhTrad = [] +{ + const walk = (o, p, area) => { + if (typeof o === 'string') { const hit = [...o].filter((c) => TRAD_ONLY.has(c)); if (hit.length) zhTrad.push(`${area}:${p} (${hit.join('')})`) } + else if (o && typeof o === 'object') for (const [k, v] of Object.entries(o)) walk(v, p ? `${p}.${k}` : k, area) + } + if (existsSync(join(ROOT, 'zh'))) for (const a of areas) { const p = join(ROOT, 'zh', a); if (existsSync(p)) walk(JSON.parse(readFileSync(p, 'utf8')), '', a) } +} +if (zhTrad.length) { + console.log(`\nI18N-PARITY: FAIL — ${zhTrad.length} zh value(s) contain Traditional-only characters; zh is Simplified:`) + for (const z of zhTrad.slice(0, 20)) console.log(` - ${z}`) + process.exit(1) +} +console.log(` zh script: no Traditional-only characters from a known set of ${TRAD_ONLY.size} (a floor, not a converter)`) console.log(`\nI18N-PARITY: PASS — no locale regressed. ${debt} key(s) of known translation debt remain.`)