mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 02:44:02 +00:00
i18n: use zh-Hant for Chinese (Traditional)
This commit is contained in:
1 parent
ddae593bb7
commit
8f16cf263b
15 files changed
+139
-110
No files matched your search
@@ -1,4 +1,4 @@
|
||||
- Add Traditional Chinese (zh-TW) with Taiwan terminology, language selection,
|
||||
- Add Traditional Chinese (zh-Hant) with language selection,
|
||||
and localized Chinese readouts. Based on translations by @caxer (#724),
|
||||
@tbdavid2019 (#652), @abiyeenzo (#914), and @EDIT-Aeterna (#979)
|
||||
(German, @gekh, #1336).
|
||||
@@ -3583,7 +3583,7 @@ test:track` 43 tracking invariants · headless QA harnesses under
|
||||
|
||||
### Interface localization (October 2026)
|
||||
|
||||
Shipped locales: **en** (source and fallback), **es**, **ru**, **zh-CN** and **zh-TW**. The code lives in
|
||||
Shipped locales: **en** (source and fallback), **es**, **ru**, **zh-CN** and **zh-Hant**. The code lives in
|
||||
`src/i18n/`. How to mark UI text: [`docs/I18N.md`](./I18N.md); translator workflow:
|
||||
[`docs/TRANSLATORS.md`](./TRANSLATORS.md).
|
||||
|
||||
@@ -3595,7 +3595,7 @@ Shipped locales: **en** (source and fallback), **es**, **ru**, **zh-CN** and **z
|
||||
`src/i18n/locales/<code>.json`, and a missing entry falls back to English.
|
||||
- **Locale choice.** `?lang=` → stored choice (`gev:locale:v1`) →
|
||||
`navigator.languages` → English. Chinese tags default to `zh-CN`; `Hant`, `TW`, `HK` and `MO`
|
||||
select `zh-TW`. Explicit `Hans` selects `zh-CN` regardless of region. `?lang=` is not stored, and share links drop
|
||||
select `zh-Hant`. Explicit `Hans` selects `zh-CN` regardless of region. `?lang=` is not stored, and share links drop
|
||||
it, so a recipient keeps their own language. The globe picker in the
|
||||
bottom-right corner (`src/ui/localePicker.js`) stores the choice, drops
|
||||
`?lang=` (keeps it only when storage is blocked) and reloads. It asks first
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# Translating God's Eye View
|
||||
|
||||
Shipped languages: **English** (source and fallback), **Spanish** (`es`), **Russian** (`ru`), **Simplified Chinese** (`zh-CN`) and **Traditional Chinese** (`zh-TW`).
|
||||
Shipped languages: **English** (source and fallback), **Spanish** (`es`), **Russian** (`ru`), **Simplified Chinese** (`zh-CN`) and **Traditional Chinese** (`zh-Hant`).
|
||||
|
||||
## How it works
|
||||
|
||||
@@ -63,4 +63,4 @@ These are contracts, not copy: layer ids and registry keys, status enums and oth
|
||||
|
||||
## Language notes
|
||||
|
||||
Each language keeps its glossary, plural forms, units and style in its own file, `docs/translations/<code>.md`: [Spanish](./translations/es.md), [Russian](./translations/ru.md), [Simplified Chinese](./translations/zh-CN.md), [Traditional Chinese](./translations/zh-TW.md). Read it before translating, and add a term there when you settle on one.
|
||||
Each language keeps its glossary, plural forms, units and style in its own file, `docs/translations/<code>.md`: [Spanish](./translations/es.md), [Russian](./translations/ru.md), [Simplified Chinese](./translations/zh-CN.md), [Traditional Chinese](./translations/zh-Hant.md). Read it before translating, and add a term there when you settle on one.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Traditional Chinese (`zh-Hant`)
|
||||
|
||||
Catalog: `src/i18n/locales/zh-Hant.json`. General rules: [TRANSLATORS.md](../TRANSLATORS.md).
|
||||
|
||||
Sources: caxer (#724), tbdavid2019 (#652), and the zh-CN catalog credited to abiyeenzo (#914) and EDIT-Aeterna (#979). The remaining entries were seeded with OpenCC s2twp and edited for consistency. The catalog retains terminology from these Taiwan-oriented sources; `zh-Hant` identifies the writing system and does not promise separate regional vocabulary.
|
||||
|
||||
## Style
|
||||
|
||||
- Use Traditional characters and consistent terminology from the glossary below. Prefer short, neutral instructions: 「點選地圖」、「儲存金鑰」.
|
||||
- Use full-width Chinese punctuation and 「」 for quotations. Keep `·`, `…`, provider names, codes and placeholders unchanged.
|
||||
- Separate Chinese from Latin letters and numbers with a space: 「AIS 船舶」、「24 小時」. Keep unit symbols unchanged: km, m, km/h, m/s, kn, ft, MW, °, %.
|
||||
- Chinese labels have no uppercase variant. Keep button labels short and avoid splitting short words across lines.
|
||||
- The picker displays 中文(繁體) / Chinese (Traditional). Browser tags with Hant or TW/HK/MO select the shared `zh-Hant` catalog. Existing `zh-TW` links and saved choices remain supported. Explicit Hans selects Simplified Chinese, including Hans-TW.
|
||||
|
||||
## Plurals
|
||||
|
||||
`Intl.PluralRules('zh-Hant')` uses only `other`. Keep suitable measure words: 「{count} 架飛機」、「{count} 艘船」、「{count} 個金鑰」.
|
||||
|
||||
## Catalog terminology
|
||||
|
||||
| English | Traditional Chinese |
|
||||
| --- | --- |
|
||||
| data / information | 資料 / 資訊 |
|
||||
| file / folder | 檔案 / 資料夾 |
|
||||
| settings / save | 設定 / 儲存 |
|
||||
| API key / token | API 金鑰 / 權杖 |
|
||||
| live / load | 即時 / 載入 |
|
||||
| camera / video | 攝影機 / 影片 |
|
||||
| network / link | 網路 / 連結 |
|
||||
| image / imagery | 圖像 / 影像 |
|
||||
| click / double-click | 點選 / 按兩下 |
|
||||
| response / timeout | 回應 / 逾時 |
|
||||
| layer / data layer | 圖層 / 資料圖層 |
|
||||
| cockpit / context | 駕駛艙 / 態勢 |
|
||||
| air quality | 空氣品質 |
|
||||
| transit / bikeshare | 大眾運輸 / 公共自行車 |
|
||||
@@ -1,36 +0,0 @@
|
||||
# Traditional Chinese (`zh-TW`)
|
||||
|
||||
Catalog: `src/i18n/locales/zh-TW.json`. General rules: [TRANSLATORS.md](../TRANSLATORS.md).
|
||||
|
||||
Sources: caxer (#724), tbdavid2019 (#652), and the zh-CN catalog credited to abiyeenzo (#914) and EDIT-Aeterna (#979). The remaining entries were seeded with OpenCC s2twp and edited for Taiwan usage.
|
||||
|
||||
## Style
|
||||
|
||||
- Use Traditional characters and Taiwan terminology. Prefer short, neutral instructions: 「點選地圖」、「儲存金鑰」.
|
||||
- Use full-width Chinese punctuation and 「」 for quotations. Keep `·`, `…`, provider names, codes and placeholders unchanged.
|
||||
- Separate Chinese from Latin letters and numbers with a space: 「AIS 船舶」、「24 小時」. Keep unit symbols unchanged: km, m, km/h, m/s, kn, ft, MW, °, %.
|
||||
- Chinese labels have no uppercase variant. Keep button labels short and avoid splitting short words across lines.
|
||||
- Browser tags with Hant or TW/HK/MO select this Taiwan catalog. Explicit Hans selects Simplified Chinese, including Hans-TW. This is not a separate Hong Kong localization.
|
||||
|
||||
## Plurals
|
||||
|
||||
`Intl.PluralRules('zh-TW')` uses only `other`. Keep suitable measure words: 「{count} 架飛機」、「{count} 艘船」、「{count} 個金鑰」.
|
||||
|
||||
## Taiwan terminology
|
||||
|
||||
| English | Taiwan | Mainland |
|
||||
| -------------------- | --------------------- | ------------------- |
|
||||
| data / information | 資料 / 資訊 | 数据 / 信息 |
|
||||
| file / folder | 檔案 / 資料夾 | 文件 / 文件夹 |
|
||||
| settings / save | 設定 / 儲存 | 设置 / 保存 |
|
||||
| API key / token | API 金鑰 / 權杖 | API 密钥 / 令牌 |
|
||||
| live / load | 即時 / 載入 | 实时 / 加载 |
|
||||
| camera / video | 攝影機 / 影片 | 摄像头 / 视频 |
|
||||
| network / link | 網路 / 連結 | 网络 / 链接 |
|
||||
| image / imagery | 圖像 / 影像 | 图像 / 影像 |
|
||||
| click / double-click | 點選 / 按兩下 | 点击 / 双击 |
|
||||
| response / timeout | 回應 / 逾時 | 响应 / 超时 |
|
||||
| layer / data layer | 圖層 / 資料圖層 | 图层 / 数据图层 |
|
||||
| cockpit / context | 駕駛艙 / 態勢 | 座舱 / 态势 |
|
||||
| air quality | 空氣品質 | 空气质量 |
|
||||
| transit / bikeshare | 大眾運輸 / 公共自行車 | 公共交通 / 共享单车 |
|
||||
@@ -442,7 +442,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": []
|
||||
},
|
||||
@@ -469,7 +469,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
},
|
||||
@@ -487,7 +487,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": []
|
||||
},
|
||||
@@ -517,7 +517,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/unitLabels.js",
|
||||
"src/ui/keyGuidance.js",
|
||||
"src/ui/statusText.js",
|
||||
@@ -539,7 +539,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": []
|
||||
},
|
||||
@@ -556,7 +556,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": []
|
||||
},
|
||||
@@ -576,7 +576,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/unitLabels.js",
|
||||
"src/ui/statusBadge.js"
|
||||
],
|
||||
@@ -603,7 +603,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/layerNames.js"
|
||||
],
|
||||
"external": []
|
||||
@@ -638,7 +638,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/unitLabels.js"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
@@ -655,7 +655,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/unitLabels.js"
|
||||
],
|
||||
"external": []
|
||||
@@ -811,7 +811,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/unitLabels.js",
|
||||
"src/ui/keyGuidance.js",
|
||||
"src/ui/layerNames.js",
|
||||
@@ -932,7 +932,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/unitLabels.js"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
@@ -999,7 +999,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/unitLabels.js"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
@@ -1047,7 +1047,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
},
|
||||
@@ -1109,7 +1109,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
},
|
||||
@@ -1139,7 +1139,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/unitLabels.js",
|
||||
"src/layers/recentImagery/display.js"
|
||||
],
|
||||
@@ -1170,7 +1170,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
},
|
||||
@@ -1202,7 +1202,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/unitLabels.js"
|
||||
],
|
||||
"external": ["cesium", "satellite.js"]
|
||||
@@ -1236,7 +1236,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
},
|
||||
@@ -1279,7 +1279,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/layers/installations/classLabel.js"
|
||||
],
|
||||
"external": ["cesium", "@mapbox/vector-tile", "pbf"]
|
||||
@@ -1315,7 +1315,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/unitLabels.js"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
@@ -1366,7 +1366,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium", "pbf", "@mapbox/vector-tile"]
|
||||
},
|
||||
@@ -1396,7 +1396,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
},
|
||||
@@ -1445,7 +1445,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["hls.js", "cesium"]
|
||||
},
|
||||
@@ -1509,7 +1509,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/layers/streetLevel/providers/mapillary/policy.js"
|
||||
],
|
||||
"external": ["cesium", "pbf", "@mapbox/vector-tile", "mapillary-js"]
|
||||
@@ -1539,7 +1539,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium", "@mapbox/vector-tile", "pbf"]
|
||||
},
|
||||
@@ -1580,7 +1580,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
},
|
||||
@@ -1603,7 +1603,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
},
|
||||
@@ -1660,7 +1660,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
},
|
||||
@@ -1717,7 +1717,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/statusText.js",
|
||||
"src/voice/providerCommands.js",
|
||||
"src/voice/providerCapabilities.js",
|
||||
@@ -2582,7 +2582,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/unitLabels.js",
|
||||
"src/layers/recentImagery/display.js",
|
||||
"src/ui/keyGuidance.js",
|
||||
@@ -3159,7 +3159,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/unitLabels.js",
|
||||
"src/layers/recentImagery/display.js",
|
||||
"src/layers/installations/classLabel.js",
|
||||
@@ -3267,7 +3267,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/i18n/index.js"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
@@ -3290,7 +3290,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": []
|
||||
},
|
||||
@@ -3326,7 +3326,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
},
|
||||
@@ -3351,7 +3351,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": []
|
||||
},
|
||||
@@ -3443,7 +3443,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/unitLabels.js"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
@@ -3499,7 +3499,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/statusText.js",
|
||||
"src/voice/providerCapabilities.js"
|
||||
],
|
||||
@@ -3754,7 +3754,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium", "egm96-universal", "pbf"]
|
||||
},
|
||||
@@ -3798,7 +3798,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium", "pbf"]
|
||||
},
|
||||
@@ -3852,7 +3852,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json"
|
||||
"src/i18n/locales/zh-Hant.json"
|
||||
],
|
||||
"external": ["cesium"]
|
||||
},
|
||||
@@ -3869,7 +3869,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/statusText.js",
|
||||
"src/ui/layerNames.js"
|
||||
],
|
||||
@@ -4063,7 +4063,7 @@
|
||||
"src/i18n/locales/es.json",
|
||||
"src/i18n/locales/ru.json",
|
||||
"src/i18n/locales/zh-CN.json",
|
||||
"src/i18n/locales/zh-TW.json",
|
||||
"src/i18n/locales/zh-Hant.json",
|
||||
"src/ui/statusText.js",
|
||||
"src/ui/layerNames.js"
|
||||
],
|
||||
|
||||
@@ -36,7 +36,7 @@ for (const [age, zh, en, tw] of cases) {
|
||||
assert.equal(methods.getStats().loadingLabel, `LIVE · updated ${en}`);
|
||||
setLocale('zh-CN');
|
||||
assert.equal(methods.getStats().loadingLabel, `实时 · 更新于 ${zh}`);
|
||||
setLocale('zh-TW');
|
||||
setLocale('zh-Hant');
|
||||
assert.equal(methods.getStats().loadingLabel, `即時 · 更新於 ${tw}`);
|
||||
} finally {
|
||||
setLocale(previousLocale);
|
||||
|
||||
@@ -39,12 +39,14 @@ test('normalizeLocale folds regional variants and rejects unshipped tags', () =>
|
||||
assert.equal(normalizeLocale('zh'), 'zh-CN');
|
||||
assert.equal(normalizeLocale('zh-CN'), 'zh-CN');
|
||||
assert.equal(normalizeLocale('zh-Hans-SG'), 'zh-CN');
|
||||
assert.equal(normalizeLocale('zh-TW'), 'zh-TW');
|
||||
assert.equal(normalizeLocale('zh-Hant-HK'), 'zh-TW');
|
||||
assert.equal(normalizeLocale('zh-Hant'), 'zh-Hant');
|
||||
assert.equal(normalizeLocale(' ZH_hant '), 'zh-Hant');
|
||||
assert.equal(normalizeLocale('zh-TW'), 'zh-Hant');
|
||||
assert.equal(normalizeLocale('zh-Hant-HK'), 'zh-Hant');
|
||||
assert.equal(normalizeLocale('zh-Hans-TW'), 'zh-CN');
|
||||
assert.equal(normalizeLocale('zh-Hant-CN'), 'zh-TW');
|
||||
assert.equal(normalizeLocale('zh_HK'), 'zh-TW');
|
||||
assert.equal(normalizeLocale('zh-MO'), 'zh-TW');
|
||||
assert.equal(normalizeLocale('zh-Hant-CN'), 'zh-Hant');
|
||||
assert.equal(normalizeLocale('zh_HK'), 'zh-Hant');
|
||||
assert.equal(normalizeLocale('zh-MO'), 'zh-Hant');
|
||||
assert.equal(normalizeLocale(undefined), null);
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -19,9 +19,9 @@ import {
|
||||
import es from './locales/es.json' with { type: 'json' };
|
||||
import ru from './locales/ru.json' with { type: 'json' };
|
||||
import zhCN from './locales/zh-CN.json' with { type: 'json' };
|
||||
import zhTW from './locales/zh-TW.json' with { type: 'json' };
|
||||
import zhHant from './locales/zh-Hant.json' with { type: 'json' };
|
||||
|
||||
const CATALOGS = Object.freeze({ es, ru, 'zh-CN': zhCN, 'zh-TW': zhTW });
|
||||
const CATALOGS = Object.freeze({ es, ru, 'zh-CN': zhCN, 'zh-Hant': zhHant });
|
||||
|
||||
let currentLocale = DEFAULT_LOCALE;
|
||||
|
||||
|
||||
+6
-5
@@ -8,15 +8,15 @@ export const LOCALE_STORAGE_KEY = 'gev:locale:v1';
|
||||
export const DEFAULT_LOCALE = 'en';
|
||||
|
||||
/** Shipped locales; order does not matter. Adding one: docs/TRANSLATORS.md. */
|
||||
export const LOCALES = Object.freeze(['en', 'es', 'ru', 'zh-CN', 'zh-TW']);
|
||||
export const LOCALES = Object.freeze(['en', 'es', 'ru', 'zh-CN', 'zh-Hant']);
|
||||
|
||||
/** Each locale named in its own language, for the selector. */
|
||||
export const LOCALE_NAMES = Object.freeze({
|
||||
en: 'English',
|
||||
es: 'Español',
|
||||
ru: 'Русский',
|
||||
'zh-CN': '简体中文',
|
||||
'zh-TW': '繁體中文',
|
||||
'zh-CN': '中文(简体)',
|
||||
'zh-Hant': '中文(繁體)',
|
||||
});
|
||||
|
||||
/** Right-to-left locales. */
|
||||
@@ -24,7 +24,8 @@ const RTL_LOCALES = Object.freeze([]);
|
||||
|
||||
/**
|
||||
* Map any language tag to a shipped locale: 'ru-RU' and 'RU' → 'ru',
|
||||
* 'zh', 'zh-CN' and 'zh-Hans-SG' → 'zh-CN'.
|
||||
* 'zh', 'zh-CN' and 'zh-Hans-SG' → 'zh-CN';
|
||||
* 'zh-Hant', 'zh-TW', 'zh-HK' and 'zh-MO' → 'zh-Hant'.
|
||||
* @returns {string|null}
|
||||
*/
|
||||
export function normalizeLocale(candidate) {
|
||||
@@ -33,7 +34,7 @@ export function normalizeLocale(candidate) {
|
||||
if (primary === 'zh') {
|
||||
if (rest.includes('hans')) return 'zh-CN';
|
||||
return rest.some((part) => ['hant', 'tw', 'hk', 'mo'].includes(part))
|
||||
? 'zh-TW'
|
||||
? 'zh-Hant'
|
||||
: 'zh-CN';
|
||||
}
|
||||
return LOCALES.includes(primary) ? primary : null;
|
||||
|
||||
File renamed without changes.
@@ -193,7 +193,7 @@
|
||||
"ΔN",
|
||||
"▲ {frp} MW"
|
||||
],
|
||||
"zh-TW": [
|
||||
"zh-Hant": [
|
||||
"1090 MHz",
|
||||
"978 MHz UAT",
|
||||
"AIS: --",
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { setLocale, t, tn, getLocale } from './index.js';
|
||||
import { resolveLocale, LOCALE_STORAGE_KEY } from './locale.js';
|
||||
import {
|
||||
resolveLocale,
|
||||
LOCALE_STORAGE_KEY,
|
||||
writeStoredLocale,
|
||||
applyDocumentLanguage,
|
||||
} from './locale.js';
|
||||
import { hudQuantity, LOCALIZED_LOCALITY } from '../hudLocalityFormat.js';
|
||||
import { formatCockpitDistance } from '../ui/cockpitPresentation.js';
|
||||
import { READOUT_WORDS } from '../layers/recentImagery/display.js';
|
||||
@@ -14,7 +19,7 @@ test('Traditional Chinese resolves from URL, saved preference and browser langua
|
||||
storage: { getItem: () => 'en' },
|
||||
languages: ['en'],
|
||||
}),
|
||||
'zh-TW',
|
||||
'zh-Hant',
|
||||
);
|
||||
assert.equal(
|
||||
resolveLocale({
|
||||
@@ -24,7 +29,7 @@ test('Traditional Chinese resolves from URL, saved preference and browser langua
|
||||
},
|
||||
languages: ['en'],
|
||||
}),
|
||||
'zh-TW',
|
||||
'zh-Hant',
|
||||
);
|
||||
assert.equal(
|
||||
resolveLocale({
|
||||
@@ -32,14 +37,29 @@ test('Traditional Chinese resolves from URL, saved preference and browser langua
|
||||
storage: { getItem: () => null },
|
||||
languages: ['zh-Hant', 'en'],
|
||||
}),
|
||||
'zh-TW',
|
||||
'zh-Hant',
|
||||
);
|
||||
});
|
||||
|
||||
test('Traditional Chinese persists and exposes the script locale for legacy choices', () => {
|
||||
const stored = new Map();
|
||||
assert.equal(
|
||||
writeStoredLocale('zh-TW', {
|
||||
setItem: (key, value) => stored.set(key, value),
|
||||
}),
|
||||
true,
|
||||
);
|
||||
assert.equal(stored.get(LOCALE_STORAGE_KEY), 'zh-Hant');
|
||||
const doc = { documentElement: {} };
|
||||
assert.equal(applyDocumentLanguage(doc, 'zh-TW'), true);
|
||||
assert.equal(doc.documentElement.lang, 'zh-Hant');
|
||||
assert.equal(doc.documentElement.dir, 'ltr');
|
||||
});
|
||||
|
||||
test('Traditional Chinese readouts preserve unit case, coordinates and natural relative dates', () => {
|
||||
const previous = getLocale();
|
||||
try {
|
||||
setLocale('zh-TW');
|
||||
setLocale('zh-Hant');
|
||||
assert.equal(hudQuantity(2069, 'km', 1), '2069.0 km');
|
||||
assert.equal(formatCockpitDistance(14000), '14\u00a0km');
|
||||
assert.equal(
|
||||
@@ -20,6 +20,11 @@ export const LOCALE_SEARCH_THRESHOLD = 8;
|
||||
/** Type-ahead keystrokes closer together than this extend one prefix. */
|
||||
export const TYPEAHEAD_RESET_MS = 500;
|
||||
|
||||
const CHINESE_LABELS = {
|
||||
'zh-CN': 'Chinese (Simplified)',
|
||||
'zh-Hant': 'Chinese (Traditional)',
|
||||
};
|
||||
|
||||
/**
|
||||
* Text folded for search: no diacritics, lower case. 'Español' → 'espanol',
|
||||
* 'Ёжик' → 'ежик'.
|
||||
@@ -464,12 +469,13 @@ export function mountLocalePicker({
|
||||
item.dataset.locale = option.code;
|
||||
const name = element(documentRef, 'span', 'locale-picker-native');
|
||||
name.textContent = option.nativeName;
|
||||
// Every row reads the same: the language named in itself, then its code.
|
||||
// The interface-language name only helps the search find it.
|
||||
// Chinese variants are distinguished by script rather than region.
|
||||
const meta = element(documentRef, 'span', 'locale-picker-meta');
|
||||
const codeLabel = element(documentRef, 'span', 'locale-picker-option-code');
|
||||
codeLabel.setAttribute('translate', 'no');
|
||||
codeLabel.textContent = option.code.toUpperCase();
|
||||
codeLabel.textContent =
|
||||
CHINESE_LABELS[option.code] || option.code.toUpperCase();
|
||||
if (CHINESE_LABELS[option.code]) codeLabel.lang = 'en';
|
||||
meta.append(codeLabel);
|
||||
const text = element(documentRef, 'span', 'locale-picker-text');
|
||||
text.append(name, meta);
|
||||
|
||||
@@ -40,7 +40,7 @@ test('the current language comes first, the rest by their own names', () => {
|
||||
nativeNames: LOCALE_NAMES,
|
||||
}),
|
||||
),
|
||||
['ru', 'en', 'es', 'zh-CN', 'zh-TW'],
|
||||
['ru', 'en', 'es', 'zh-CN', 'zh-Hant'],
|
||||
);
|
||||
assert.deepEqual(
|
||||
codes(
|
||||
@@ -50,7 +50,7 @@ test('the current language comes first, the rest by their own names', () => {
|
||||
nativeNames: LOCALE_NAMES,
|
||||
}),
|
||||
),
|
||||
['es', 'en', 'ru', 'zh-CN', 'zh-TW'],
|
||||
['es', 'en', 'ru', 'zh-CN', 'zh-Hant'],
|
||||
);
|
||||
assert.deepEqual(
|
||||
codes(
|
||||
@@ -60,7 +60,7 @@ test('the current language comes first, the rest by their own names', () => {
|
||||
nativeNames: LOCALE_NAMES,
|
||||
}),
|
||||
),
|
||||
['en', 'es', 'ru', 'zh-CN', 'zh-TW'],
|
||||
['en', 'es', 'ru', 'zh-CN', 'zh-Hant'],
|
||||
);
|
||||
const rows = buildLocaleOptions({
|
||||
locales: MANY,
|
||||
@@ -263,7 +263,7 @@ test('keyboard model: open on the current language, move, choose, close', () =>
|
||||
assert.deepEqual(model.keydown({ key: 'ArrowDown' }), { handled: true });
|
||||
assert.equal(model.activeOption.code, 'en');
|
||||
model.keydown({ key: 'End' });
|
||||
assert.equal(model.activeOption.code, 'zh-TW');
|
||||
assert.equal(model.activeOption.code, 'zh-Hant');
|
||||
model.keydown({ key: 'Home' });
|
||||
assert.equal(model.activeOption.code, 'ru');
|
||||
model.keydown({ key: 'ArrowUp' });
|
||||
|
||||
Reference in new issue
Block a user