Complete Thai and English translations across the UI
Deploy GaC-Srtool to GitHub Pages / deploy (push) Waiting to run
Deploy GaC-Srtool to GitHub Pages / deploy (push) Waiting to run
This commit is contained in:
1 parent
1593581729
commit
02be735377
9 files changed
+131
-51
No files matched your search
+21
-6
@@ -341,8 +341,8 @@ battle_config = {
|
|||||||
| ไฟล์ | เวอร์ชันใหม่ |
|
| ไฟล์ | เวอร์ชันใหม่ |
|
||||||
| :--- | :--- |
|
| :--- | :--- |
|
||||||
| `css/styles.css` | `2.36` |
|
| `css/styles.css` | `2.36` |
|
||||||
| `js/app.js` | `3.32` |
|
| `js/app.js` | `3.33` |
|
||||||
| `js/i18n.js` | `2.26` (ทุก importer ต้องตรงกัน) |
|
| `js/i18n.js` | `2.27` (ทุก importer ต้องตรงกัน) |
|
||||||
| `js/endgame.js` | `1` (ไฟล์ใหม่) |
|
| `js/endgame.js` | `1` (ไฟล์ใหม่) |
|
||||||
|
|
||||||
Importer ของ `i18n.js` ที่ถูกแก้: `index.html` (ทาง `app.js`), `js/app.js`, `js/avatars-data.js`, `js/equipment-data.js`, `js/item-catalog.js`, `js/unstuck.js`
|
Importer ของ `i18n.js` ที่ถูกแก้: `index.html` (ทาง `app.js`), `js/app.js`, `js/avatars-data.js`, `js/equipment-data.js`, `js/item-catalog.js`, `js/unstuck.js`
|
||||||
@@ -358,6 +358,7 @@ Importer ของ `i18n.js` ที่ถูกแก้: `index.html` (ทา
|
|||||||
| `scripts/build-firefly-endgame-data.cjs` | สร้างแคตตาล็อกจาก API ต้นฉบับ |
|
| `scripts/build-firefly-endgame-data.cjs` | สร้างแคตตาล็อกจาก API ต้นฉบับ |
|
||||||
| `assets/firefly-endgame.json` | แคตตาล็อกพร้อมใช้ (~604 KB) |
|
| `assets/firefly-endgame.json` | แคตตาล็อกพร้อมใช้ (~604 KB) |
|
||||||
| `tests/endgame.test.cjs` | unit tests ของ endgame helpers (8 tests) |
|
| `tests/endgame.test.cjs` | unit tests ของ endgame helpers (8 tests) |
|
||||||
|
| `tests/i18n-coverage.test.cjs` | ตรวจว่า `data-i18n*` ทุกคีย์ resolve ได้ทั้ง th/en |
|
||||||
|
|
||||||
### แก้ไข
|
### แก้ไข
|
||||||
| ไฟล์ | สิ่งที่แก้ |
|
| ไฟล์ | สิ่งที่แก้ |
|
||||||
@@ -368,7 +369,7 @@ Importer ของ `i18n.js` ที่ถูกแก้: `index.html` (ทา
|
|||||||
| `js/firefly.js` | normalize `blessings` / `monsters` ให้ตรง zod |
|
| `js/firefly.js` | normalize `blessings` / `monsters` ให้ตรง zod |
|
||||||
| `js/i18n.js` | เพิ่ม 46 คีย์ th/en, bump version |
|
| `js/i18n.js` | เพิ่ม 46 คีย์ th/en, bump version |
|
||||||
| `css/styles.css` | สไตล์ `.ff-endgame-*` + responsive |
|
| `css/styles.css` | สไตล์ `.ff-endgame-*` + responsive |
|
||||||
| `js/avatars-data.js`, `js/equipment-data.js`, `js/item-catalog.js`, `js/unstuck.js` | bump `i18n.js?v=2.26` (และ bump version ของ module ปลายทางใน `app.js`) |
|
| `js/avatars-data.js`, `js/equipment-data.js`, `js/item-catalog.js`, `js/unstuck.js` | bump `i18n.js?v=2.27` (และ bump version ของ module ปลายทางใน `app.js`) |
|
||||||
| `tests/firefly-payload.test.cjs` | อัปเดต expected shape + เพิ่ม test normalize |
|
| `tests/firefly-payload.test.cjs` | อัปเดต expected shape + เพิ่ม test normalize |
|
||||||
| `tests/mode-capabilities.test.cjs` | เพิ่ม `fireflyEndgame`, คีย์ i18n, DOM hooks |
|
| `tests/mode-capabilities.test.cjs` | เพิ่ม `fireflyEndgame`, คีย์ i18n, DOM hooks |
|
||||||
|
|
||||||
@@ -423,8 +424,8 @@ Importer ของ `i18n.js` ที่ถูกแก้: `index.html` (ทา
|
|||||||
### 5.6 Tests
|
### 5.6 Tests
|
||||||
```
|
```
|
||||||
node --test tests/*.test.cjs
|
node --test tests/*.test.cjs
|
||||||
ℹ tests 44
|
ℹ tests 47
|
||||||
ℹ pass 44
|
ℹ pass 47
|
||||||
ℹ fail 0
|
ℹ fail 0
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -433,6 +434,7 @@ node --test tests/*.test.cjs
|
|||||||
- การ normalize `blessings` / `monsters` (รวม `dynamic_key`)
|
- การ normalize `blessings` / `monsters` (รวม `dynamic_key`)
|
||||||
- capability matrix + i18n keys + DOM hooks
|
- capability matrix + i18n keys + DOM hooks
|
||||||
- endgame helpers: default/resolve/build/challenge/find-by-stage/custom
|
- endgame helpers: default/resolve/build/challenge/find-by-stage/custom
|
||||||
|
- **i18n coverage:** ทุก `data-i18n*` ใน `index.html` ต้อง resolve ได้ทั้ง th/en
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -456,6 +458,18 @@ node --test tests/*.test.cjs
|
|||||||
|
|
||||||
**แก้โดย:** เพิ่ม `applyFireflyEndgameStatus()` ที่อ่าน `state.fireflyEndgame.statusKey/statusState/statusVars` แล้วเรียกที่ท้าย `renderFireflyEndgame()` ทั้งสอง branch (ทั้งตอน catalog ยังไม่โหลดและตอนเรนเดอร์ปกติ) — ตอนนี้สถานะถูกต้องหลังสลับภาษา
|
**แก้โดย:** เพิ่ม `applyFireflyEndgameStatus()` ที่อ่าน `state.fireflyEndgame.statusKey/statusState/statusVars` แล้วเรียกที่ท้าย `renderFireflyEndgame()` ทั้งสอง branch (ทั้งตอน catalog ยังไม่โหลดและตอนเรนเดอร์ปกติ) — ตอนนี้สถานะถูกต้องหลังสลับภาษา
|
||||||
|
|
||||||
|
### 6.1.2 🐞 บั๊ก i18n ที่พบเพิ่มเติมและแก้แล้ว
|
||||||
|
ตรวจทั้งโปรเจกต์ด้วยสคริปต์ (เทียบ `data-i18n*` ใน `index.html` + คีย์จาก `t()` ทุกไฟล์ กับ `TRANSLATIONS.th/en`) พบว่า:
|
||||||
|
|
||||||
|
1. **ชื่อธาตุ/สายไม่เคยถูกแปล** — `<option data-i18n="Fire">` แต่พจนานุกรมเก็บไว้ใต้ `elements.Fire` / `paths.Destruction` ทำให้ `t('Fire')` คืนค่าเป็นคีย์เดิม แล้ว `applyTranslations()` ข้ามการอัปเดต (เงื่อนไข `val !== key`) — แก้เป็น `data-i18n="elements.Fire"` และ `data-i18n="paths.Destruction"` ครบทั้ง 34 จุด (7 ธาตุ + 9 สาย × หลาย dropdown)
|
||||||
|
2. **`fireflyTheoryModeHint` ไม่มีในพจนานุกรมทั้ง th/en** — ข้อความใต้สวิตช์ Creative Mode จึงไม่เคยเปลี่ยนภาษา แก้โดยเพิ่ม th/en
|
||||||
|
3. **บรรทัดพจนานุกรมไทยถูก merge ข้ามภาษา** — บรรทัดเดียวมีคีย์ `analystDamageAvPlaceholder`, `analystCyclesPlaceholder`, `analystTurnsPlaceholder`, `analystAutoTurnsPlaceholder`, `miniViewFullAnalystTooltip` ซ้ำกัน 13 ภาษา (ค่าที่ชนะคือภาษาโปรตุเกส) และ `copyCardGenerated` หายไป — แยกกลับเป็นค่าภาษาไทยที่ถูกต้อง และเพิ่มคีย์ภาษาอังกฤษที่ขาด
|
||||||
|
4. **`miniViewFullAnalystTooltip` และ analyst placeholders ไม่มีใน en** — เพิ่มครบแล้ว
|
||||||
|
|
||||||
|
เพิ่มเทสต์กันพลาดซ้ำ: `tests/i18n-coverage.test.cjs` ตรวจว่า **ทุก** `data-i18n`, `data-i18n-placeholder`, `data-i18n-title`, `data-i18n-alt`, `data-i18n-aria-label` ใน `index.html` resolve ได้ทั้ง th และ en (รองรับ dotted key) และตรวจ nested `elements.*` / `paths.*`
|
||||||
|
|
||||||
|
**ผลตรวจหลังแก้:** data-i18n missing th = 0, en = 0; t() missing th = 0, en = 0
|
||||||
|
|
||||||
### 6.2 ✅ ทดสอบมือถือ 360–768px
|
### 6.2 ✅ ทดสอบมือถือ 360–768px
|
||||||
**สถานะ:** ทดสอบด้วย iframe ขนาด 360×800 และ 768×1024 (media query ภายใน iframe ทำงานเหมือน viewport จริง)
|
**สถานะ:** ทดสอบด้วย iframe ขนาด 360×800 และ 768×1024 (media query ภายใน iframe ทำงานเหมือน viewport จริง)
|
||||||
|
|
||||||
@@ -547,7 +561,8 @@ node scripts/dev-server.cjs
|
|||||||
- [x] เปลี่ยนภาษาแล้วหน้า picker รีเรนเดอร์ และสถานะไม่ค้างที่ loading
|
- [x] เปลี่ยนภาษาแล้วหน้า picker รีเรนเดอร์ และสถานะไม่ค้างที่ loading
|
||||||
- [x] มือถือ 360px ไม่มี horizontal scroll และปุ่ม ≥44px
|
- [x] มือถือ 360px ไม่มี horizontal scroll และปุ่ม ≥44px
|
||||||
- [x] โหมด GaCy เดิมยังทำงาน (Monster Setting เดิม, Aha's Help, custom waves)
|
- [x] โหมด GaCy เดิมยังทำงาน (Monster Setting เดิม, Aha's Help, custom waves)
|
||||||
- [x] `?v=` ถูก bump ครบ (`styles.css 2.36`, `app.js 3.32`, `i18n.js 2.26` ทุก importer)
|
- [x] `?v=` ถูก bump ครบ (`styles.css 2.36`, `app.js 3.33`, `i18n.js 2.27` ทุก importer)
|
||||||
- [x] ไม่มีข้อความ hardcode ใหม่ใน HTML/JS
|
- [x] ไม่มีข้อความ hardcode ใหม่ใน HTML/JS
|
||||||
|
- [x] ทุก `data-i18n*` resolve ได้ทั้ง th/en (มีเทสต์บังคับ)
|
||||||
- [x] ไม่แก้ `README.md`
|
- [x] ไม่แก้ `README.md`
|
||||||
- [ ] ทดสอบ `POST /sync` happy path กับ FireflyGO จริง (ต้องมีเซิร์ฟเวอร์)
|
- [ ] ทดสอบ `POST /sync` happy path กับ FireflyGO จริง (ต้องมีเซิร์ฟเวอร์)
|
||||||
+35
-35
@@ -304,25 +304,25 @@
|
|||||||
</select>
|
</select>
|
||||||
<select id="avatar-filter-element" class="form-select" style="max-width: 130px;">
|
<select id="avatar-filter-element" class="form-select" style="max-width: 130px;">
|
||||||
<option value="all" data-i18n="filterAllElements">ทุกธาตุ</option>
|
<option value="all" data-i18n="filterAllElements">ทุกธาตุ</option>
|
||||||
<option value="Fire" data-i18n="Fire">ไฟ</option>
|
<option value="Fire" data-i18n="elements.Fire">ไฟ</option>
|
||||||
<option value="Ice" data-i18n="Ice">น้ำแข็ง</option>
|
<option value="Ice" data-i18n="elements.Ice">น้ำแข็ง</option>
|
||||||
<option value="Lightning" data-i18n="Lightning">สายฟ้า</option>
|
<option value="Lightning" data-i18n="elements.Lightning">สายฟ้า</option>
|
||||||
<option value="Wind" data-i18n="Wind">ลม</option>
|
<option value="Wind" data-i18n="elements.Wind">ลม</option>
|
||||||
<option value="Physical" data-i18n="Physical">กายภาพ</option>
|
<option value="Physical" data-i18n="elements.Physical">กายภาพ</option>
|
||||||
<option value="Quantum" data-i18n="Quantum">ควอนตัม</option>
|
<option value="Quantum" data-i18n="elements.Quantum">ควอนตัม</option>
|
||||||
<option value="Imaginary" data-i18n="Imaginary">จินตภาพ</option>
|
<option value="Imaginary" data-i18n="elements.Imaginary">จินตภาพ</option>
|
||||||
</select>
|
</select>
|
||||||
<select id="avatar-filter-path" class="form-select" style="max-width: 130px;">
|
<select id="avatar-filter-path" class="form-select" style="max-width: 130px;">
|
||||||
<option value="all" data-i18n="filterAllPaths">ทุกประเภท</option>
|
<option value="all" data-i18n="filterAllPaths">ทุกประเภท</option>
|
||||||
<option value="Destruction" data-i18n="Destruction">ทำลายล้าง</option>
|
<option value="Destruction" data-i18n="paths.Destruction">ทำลายล้าง</option>
|
||||||
<option value="Hunt" data-i18n="Hunt">ล่าสังหาร</option>
|
<option value="Hunt" data-i18n="paths.Hunt">ล่าสังหาร</option>
|
||||||
<option value="Erudition" data-i18n="Erudition">ปัญญา</option>
|
<option value="Erudition" data-i18n="paths.Erudition">ปัญญา</option>
|
||||||
<option value="Harmony" data-i18n="Harmony">ประสาน</option>
|
<option value="Harmony" data-i18n="paths.Harmony">ประสาน</option>
|
||||||
<option value="Nihility" data-i18n="Nihility">ลบล้าง</option>
|
<option value="Nihility" data-i18n="paths.Nihility">ลบล้าง</option>
|
||||||
<option value="Preservation" data-i18n="Preservation">อนุรักษ์</option>
|
<option value="Preservation" data-i18n="paths.Preservation">อนุรักษ์</option>
|
||||||
<option value="Abundance" data-i18n="Abundance">เฟื่องฟู</option>
|
<option value="Abundance" data-i18n="paths.Abundance">เฟื่องฟู</option>
|
||||||
<option value="Remembrance" data-i18n="Remembrance">ความทรงจำ</option>
|
<option value="Remembrance" data-i18n="paths.Remembrance">ความทรงจำ</option>
|
||||||
<option value="Elation" data-i18n="Elation">ปีติ</option>
|
<option value="Elation" data-i18n="paths.Elation">ปีติ</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
|
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
|
||||||
@@ -1728,15 +1728,15 @@
|
|||||||
<input type="text" id="add-lc-search" class="form-input" data-i18n-placeholder="lightConeSearchPlaceholder" placeholder="🔍 ค้นหากรวยแสง (ชื่อหรือ ID)..." style="flex: 1; min-width: 160px;">
|
<input type="text" id="add-lc-search" class="form-input" data-i18n-placeholder="lightConeSearchPlaceholder" placeholder="🔍 ค้นหากรวยแสง (ชื่อหรือ ID)..." style="flex: 1; min-width: 160px;">
|
||||||
<select id="add-lc-filter-path" class="form-select" style="max-width: 140px;">
|
<select id="add-lc-filter-path" class="form-select" style="max-width: 140px;">
|
||||||
<option value="all" data-i18n="filterAllPaths">ทุกสาย (All)</option>
|
<option value="all" data-i18n="filterAllPaths">ทุกสาย (All)</option>
|
||||||
<option value="Destruction" data-i18n="Destruction">ทำลายล้าง</option>
|
<option value="Destruction" data-i18n="paths.Destruction">ทำลายล้าง</option>
|
||||||
<option value="Hunt" data-i18n="Hunt">ล่าสังหาร</option>
|
<option value="Hunt" data-i18n="paths.Hunt">ล่าสังหาร</option>
|
||||||
<option value="Erudition" data-i18n="Erudition">ปัญญา</option>
|
<option value="Erudition" data-i18n="paths.Erudition">ปัญญา</option>
|
||||||
<option value="Harmony" data-i18n="Harmony">ประสาน</option>
|
<option value="Harmony" data-i18n="paths.Harmony">ประสาน</option>
|
||||||
<option value="Nihility" data-i18n="Nihility">ลบล้าง</option>
|
<option value="Nihility" data-i18n="paths.Nihility">ลบล้าง</option>
|
||||||
<option value="Preservation" data-i18n="Preservation">อนุรักษ์</option>
|
<option value="Preservation" data-i18n="paths.Preservation">อนุรักษ์</option>
|
||||||
<option value="Abundance" data-i18n="Abundance">เฟื่องฟู</option>
|
<option value="Abundance" data-i18n="paths.Abundance">เฟื่องฟู</option>
|
||||||
<option value="Remembrance" data-i18n="Remembrance">ความทรงจำ</option>
|
<option value="Remembrance" data-i18n="paths.Remembrance">ความทรงจำ</option>
|
||||||
<option value="Elation" data-i18n="Elation">ปีติ</option>
|
<option value="Elation" data-i18n="paths.Elation">ปีติ</option>
|
||||||
</select>
|
</select>
|
||||||
<select id="add-lc-filter-rarity" class="form-select" style="max-width: 110px;">
|
<select id="add-lc-filter-rarity" class="form-select" style="max-width: 110px;">
|
||||||
<option value="all" data-i18n="filterAllRarity">ทุกระดับดาว</option>
|
<option value="all" data-i18n="filterAllRarity">ทุกระดับดาว</option>
|
||||||
@@ -1993,15 +1993,15 @@
|
|||||||
<select id="lc-picker-filter-path" class="form-select" style="max-width: 140px;">
|
<select id="lc-picker-filter-path" class="form-select" style="max-width: 140px;">
|
||||||
<option value="all" data-i18n="filterAllPaths">ทุกสาย</option>
|
<option value="all" data-i18n="filterAllPaths">ทุกสาย</option>
|
||||||
<option value="same" selected data-i18n="filterSamePath">ตรงสายตัวละคร</option>
|
<option value="same" selected data-i18n="filterSamePath">ตรงสายตัวละคร</option>
|
||||||
<option value="Destruction" data-i18n="Destruction">ทำลายล้าง</option>
|
<option value="Destruction" data-i18n="paths.Destruction">ทำลายล้าง</option>
|
||||||
<option value="Hunt" data-i18n="Hunt">ล่าสังหาร</option>
|
<option value="Hunt" data-i18n="paths.Hunt">ล่าสังหาร</option>
|
||||||
<option value="Erudition" data-i18n="Erudition">ปัญญา</option>
|
<option value="Erudition" data-i18n="paths.Erudition">ปัญญา</option>
|
||||||
<option value="Harmony" data-i18n="Harmony">ประสาน</option>
|
<option value="Harmony" data-i18n="paths.Harmony">ประสาน</option>
|
||||||
<option value="Nihility" data-i18n="Nihility">ลบล้าง</option>
|
<option value="Nihility" data-i18n="paths.Nihility">ลบล้าง</option>
|
||||||
<option value="Preservation" data-i18n="Preservation">อนุรักษ์</option>
|
<option value="Preservation" data-i18n="paths.Preservation">อนุรักษ์</option>
|
||||||
<option value="Abundance" data-i18n="Abundance">เฟื่องฟู</option>
|
<option value="Abundance" data-i18n="paths.Abundance">เฟื่องฟู</option>
|
||||||
<option value="Remembrance" data-i18n="Remembrance">ความทรงจำ</option>
|
<option value="Remembrance" data-i18n="paths.Remembrance">ความทรงจำ</option>
|
||||||
<option value="Elation" data-i18n="Elation">ปีติ</option>
|
<option value="Elation" data-i18n="paths.Elation">ปีติ</option>
|
||||||
</select>
|
</select>
|
||||||
<select id="lc-picker-rank" class="form-select" style="max-width: 110px;" data-i18n-title="superimpositionSelectTitle" title="ระดับการขัดเกลาเมื่อสวมใส่">
|
<select id="lc-picker-rank" class="form-select" style="max-width: 110px;" data-i18n-title="superimpositionSelectTitle" title="ระดับการขัดเกลาเมื่อสวมใส่">
|
||||||
<option value="5" selected data-superimposition-rank>ขัดเกลา S5</option>
|
<option value="5" selected data-superimposition-rank>ขัดเกลา S5</option>
|
||||||
@@ -2079,6 +2079,6 @@
|
|||||||
<div class="toast-container" id="toast-container"></div>
|
<div class="toast-container" id="toast-container"></div>
|
||||||
|
|
||||||
<!-- Script Modules -->
|
<!-- Script Modules -->
|
||||||
<script type="module" src="js/app.js?v=3.32"></script>
|
<script type="module" src="js/app.js?v=3.33"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import { COMMANDS, usage, inspectCommand, completeCommand, setCommandLanguage, describeCommand } from './command-assistant.mjs';
|
import { COMMANDS, usage, inspectCommand, completeCommand, setCommandLanguage, describeCommand } from './command-assistant.mjs';
|
||||||
import { AVATAR_METADATA, getAvatarInfo } from './avatars-data.js?v=2.22';
|
import { AVATAR_METADATA, getAvatarInfo } from './avatars-data.js?v=2.23';
|
||||||
import { LIGHTCONE_METADATA, RELIC_SET_METADATA, getLightconeInfo, getRelicSetInfo } from './equipment-data.js?v=2.28';
|
import { LIGHTCONE_METADATA, RELIC_SET_METADATA, getLightconeInfo, getRelicSetInfo } from './equipment-data.js?v=2.29';
|
||||||
import { initializeItemCatalog } from './item-catalog.js?v=6';
|
import { initializeItemCatalog } from './item-catalog.js?v=7';
|
||||||
import { initializeUnstuck } from './unstuck.js?v=5';
|
import { initializeUnstuck } from './unstuck.js?v=6';
|
||||||
import { PRYDWEN_BUILD_GUIDES } from './build-guides-data.js';
|
import { PRYDWEN_BUILD_GUIDES } from './build-guides-data.js';
|
||||||
import { SUPPORTED_LANGUAGES, TRANSLATIONS, getCurrentLanguage, setLanguage, t, translateElement, translatePath } from './i18n.js?v=2.26';
|
import { SUPPORTED_LANGUAGES, TRANSLATIONS, getCurrentLanguage, setLanguage, t, translateElement, translatePath } from './i18n.js?v=2.27';
|
||||||
import { enkaToFreeSR, mergeFreeSR, countFreeSRContent, normalizeEnkaUid } from './enka-import.js?v=1';
|
import { enkaToFreeSR, mergeFreeSR, countFreeSRContent, normalizeEnkaUid } from './enka-import.js?v=1';
|
||||||
import { buildSyncPayload, normalizeExtraData, fireflySyncUrl, FIREFLY_EXTRA_FALLBACK } from './firefly.js?v=1';
|
import { buildSyncPayload, normalizeExtraData, fireflySyncUrl, FIREFLY_EXTRA_FALLBACK } from './firefly.js?v=1';
|
||||||
import { MODE_LABELS, normalizeMode, modeCapabilities, modeSupports } from './modes.js?v=1';
|
import { MODE_LABELS, normalizeMode, modeCapabilities, modeSupports } from './modes.js?v=1';
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { getCurrentLanguage, translateElement, translatePath } from "./i18n.js?v=2.26";
|
import { getCurrentLanguage, translateElement, translatePath } from "./i18n.js?v=2.27";
|
||||||
|
|
||||||
export const AVATAR_METADATA = {
|
export const AVATAR_METADATA = {
|
||||||
"1001": {
|
"1001": {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getCurrentLanguage, translatePath } from "./i18n.js?v=2.26";
|
import { getCurrentLanguage, translatePath } from "./i18n.js?v=2.27";
|
||||||
|
|
||||||
export const LIGHTCONE_METADATA = {
|
export const LIGHTCONE_METADATA = {
|
||||||
"20000": {
|
"20000": {
|
||||||
|
|||||||
+13
-1
@@ -7255,12 +7255,18 @@ const MODAL_AND_TOOL_TRANSLATIONS = {
|
|||||||
relicSetSearchLabel: 'ค้นหาชุดรีลิกส์',
|
relicSetSearchLabel: 'ค้นหาชุดรีลิกส์',
|
||||||
relicSetSearchPlaceholder: '🔍 ค้นหาชุดรีลิกส์...',
|
relicSetSearchPlaceholder: '🔍 ค้นหาชุดรีลิกส์...',
|
||||||
relicSetGridLabel: 'ชุดรีลิกส์',
|
relicSetGridLabel: 'ชุดรีลิกส์',
|
||||||
analystDamageAvPlaceholder: "เฉลี่ยต่อรอบ: -", analystCyclesPlaceholder: "0 รอบ", analystTurnsPlaceholder: "0 เทิร์น", analystAutoTurnsPlaceholder: "เทิร์นอัตโนมัติ: 0", analystDamageAvPlaceholder: "Avg per cycle: -", analystCyclesPlaceholder: "0 Cycles", analystTurnsPlaceholder: "0 Turns", analystAutoTurnsPlaceholder: "Auto Turns: 0", analystDamageAvPlaceholder: "ラウンド平均: -", analystCyclesPlaceholder: "0 ラウンド", analystTurnsPlaceholder: "0 ターン", analystAutoTurnsPlaceholder: "オートターン: 0", analystDamageAvPlaceholder: "라운드당 평균: -", analystCyclesPlaceholder: "0 라운드", analystTurnsPlaceholder: "0 턴", analystAutoTurnsPlaceholder: "자동 턴: 0", analystDamageAvPlaceholder: "Trung bình mỗi vòng: -", analystCyclesPlaceholder: "0 vòng", analystTurnsPlaceholder: "0 lượt", analystAutoTurnsPlaceholder: "Lượt tự động: 0", analystDamageAvPlaceholder: "Rata-rata per siklus: -", analystCyclesPlaceholder: "0 Siklus", analystTurnsPlaceholder: "0 Giliran", analystAutoTurnsPlaceholder: "Giliran otomatis: 0", analystDamageAvPlaceholder: "Promedio por ciclo: -", analystCyclesPlaceholder: "0 ciclos", analystTurnsPlaceholder: "0 turnos", analystAutoTurnsPlaceholder: "Turnos automáticos: 0", analystDamageAvPlaceholder: "Moyenne par cycle : -", analystCyclesPlaceholder: "0 cycle", analystTurnsPlaceholder: "0 tour", analystAutoTurnsPlaceholder: "Tours auto : 0", analystDamageAvPlaceholder: "Durchschnitt pro Zyklus: -", analystCyclesPlaceholder: "0 Zyklen", analystTurnsPlaceholder: "0 Züge", analystAutoTurnsPlaceholder: "Auto-Züge: 0", analystDamageAvPlaceholder: "В среднем за цикл: -", analystCyclesPlaceholder: "0 циклов", analystTurnsPlaceholder: "0 ходов", analystAutoTurnsPlaceholder: "Авто-ходы: 0", analystDamageAvPlaceholder: "Média por ciclo: -", analystCyclesPlaceholder: "0 ciclos", analystTurnsPlaceholder: "0 turnos", analystAutoTurnsPlaceholder: "Turnos automáticos: 0", miniViewFullAnalystTooltip: "เปิดหน้า Damage Analyst ตัวเต็ม", miniViewFullAnalystTooltip: "Open full Damage Analyst", miniViewFullAnalystTooltip: "完全なダメージ分析を開く", miniViewFullAnalystTooltip: "전체 데미지 분석 열기", miniViewFullAnalystTooltip: "Mở Trình phân tích sát thương đầy đủ", miniViewFullAnalystTooltip: "Buka Analis Kerusakan Lengkap", miniViewFullAnalystTooltip: "Abrir analizador de daño completo", miniViewFullAnalystTooltip: "Ouvrir l'analyseur de dégâts complet", miniViewFullAnalystTooltip: "Vollständigen Schadensanalysten öffnen", miniViewFullAnalystTooltip: "Открыть полный анализ урона", miniViewFullAnalystTooltip: "Abrir analisador de dano completo", copyCardGenerated: 'สร้างโดย GaCy-Srtool',
|
analystDamageAvPlaceholder: 'เฉลี่ยต่อรอบ: -',
|
||||||
|
analystCyclesPlaceholder: '0 รอบ',
|
||||||
|
analystTurnsPlaceholder: '0 เทิร์น',
|
||||||
|
analystAutoTurnsPlaceholder: 'เทิร์นอัตโนมัติ: 0',
|
||||||
|
miniViewFullAnalystTooltip: 'เปิดหน้า Damage Analyst ตัวเต็ม',
|
||||||
|
copyCardGenerated: 'สร้างโดย GaCy-Srtool',
|
||||||
// FireflyGo endgame room picker
|
// FireflyGo endgame room picker
|
||||||
ffEndgameTitle: '🦋 ห้อง Endgame (FireflyGO)',
|
ffEndgameTitle: '🦋 ห้อง Endgame (FireflyGO)',
|
||||||
ffEndgameTablistLabel: 'โหมดด่าน endgame ของ FireflyGO',
|
ffEndgameTablistLabel: 'โหมดด่าน endgame ของ FireflyGO',
|
||||||
ffEndgameDescription: 'เลือกด่าน endgame และคลื่นมอนที่ FireflyGO จะใช้ แล้วเขียนลง battle_config โดยตรง',
|
ffEndgameDescription: 'เลือกด่าน endgame และคลื่นมอนที่ FireflyGO จะใช้ แล้วเขียนลง battle_config โดยตรง',
|
||||||
ffEndgameRule: 'ค่าเหล่านี้เขียนลง battle_config (และ extra_data.challenge สำหรับ Anomaly Arbitration) จากนั้นบันทึกในเครื่องหรือซิงค์ขึ้น FireflyGO',
|
ffEndgameRule: 'ค่าเหล่านี้เขียนลง battle_config (และ extra_data.challenge สำหรับ Anomaly Arbitration) จากนั้นบันทึกในเครื่องหรือซิงค์ขึ้น FireflyGO',
|
||||||
|
fireflyTheoryModeHint: 'สวิตช์นี้คือโหมดสร้างสรรค์ (Creative Mode) — เปิดจากที่ไหนก็ได้ อีกสวิตช์จะตามให้อัตโนมัติ',
|
||||||
ffEndgameModePeak: 'Anomaly Arbitration',
|
ffEndgameModePeak: 'Anomaly Arbitration',
|
||||||
ffEndgameLoading: 'กำลังโหลดข้อมูลด่าน endgame…',
|
ffEndgameLoading: 'กำลังโหลดข้อมูลด่าน endgame…',
|
||||||
ffEndgameReady: 'พร้อมใช้งาน · เลือกห้องแล้วกดใช้กับ battle_config',
|
ffEndgameReady: 'พร้อมใช้งาน · เลือกห้องแล้วกดใช้กับ battle_config',
|
||||||
@@ -7512,6 +7518,11 @@ const MODAL_AND_TOOL_TRANSLATIONS = {
|
|||||||
relicSetSearchLabel: 'Search relic sets',
|
relicSetSearchLabel: 'Search relic sets',
|
||||||
relicSetSearchPlaceholder: '🔍 Search relic sets...',
|
relicSetSearchPlaceholder: '🔍 Search relic sets...',
|
||||||
relicSetGridLabel: 'Relic sets',
|
relicSetGridLabel: 'Relic sets',
|
||||||
|
analystDamageAvPlaceholder: 'Avg per cycle: -',
|
||||||
|
analystCyclesPlaceholder: '0 Cycles',
|
||||||
|
analystTurnsPlaceholder: '0 Turns',
|
||||||
|
analystAutoTurnsPlaceholder: 'Auto Turns: 0',
|
||||||
|
miniViewFullAnalystTooltip: 'Open full Damage Analyst',
|
||||||
copyCardGenerated: 'Generated via GaCy-Srtool',
|
copyCardGenerated: 'Generated via GaCy-Srtool',
|
||||||
|
|
||||||
// FireflyGo endgame room picker
|
// FireflyGo endgame room picker
|
||||||
@@ -7519,6 +7530,7 @@ const MODAL_AND_TOOL_TRANSLATIONS = {
|
|||||||
ffEndgameTablistLabel: 'FireflyGO endgame room modes',
|
ffEndgameTablistLabel: 'FireflyGO endgame room modes',
|
||||||
ffEndgameDescription: 'Pick the endgame room and monster waves FireflyGO should load, then write them straight into battle_config.',
|
ffEndgameDescription: 'Pick the endgame room and monster waves FireflyGO should load, then write them straight into battle_config.',
|
||||||
ffEndgameRule: 'These values are written to battle_config (plus extra_data.challenge for Anomaly Arbitration), then saved locally or synced to FireflyGO.',
|
ffEndgameRule: 'These values are written to battle_config (plus extra_data.challenge for Anomaly Arbitration), then saved locally or synced to FireflyGO.',
|
||||||
|
fireflyTheoryModeHint: 'This switch is Creative Mode — turn it on anywhere and the other switch follows automatically.',
|
||||||
ffEndgameModePeak: 'Anomaly Arbitration',
|
ffEndgameModePeak: 'Anomaly Arbitration',
|
||||||
ffEndgameLoading: 'Loading endgame data…',
|
ffEndgameLoading: 'Loading endgame data…',
|
||||||
ffEndgameReady: 'Ready · pick a room, then apply it to battle_config',
|
ffEndgameReady: 'Ready · pick a room, then apply it to battle_config',
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { getCurrentLanguage, t, translatePath } from './i18n.js?v=2.26';
|
import { getCurrentLanguage, t, translatePath } from './i18n.js?v=2.27';
|
||||||
|
|
||||||
const CATALOG_URL = new URL('../assets/item-catalog.json?v=2', import.meta.url);
|
const CATALOG_URL = new URL('../assets/item-catalog.json?v=2', import.meta.url);
|
||||||
const PAGE_SIZE = 48;
|
const PAGE_SIZE = 48;
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { getCurrentLanguage } from './i18n.js?v=2.26';
|
import { getCurrentLanguage } from './i18n.js?v=2.27';
|
||||||
|
|
||||||
const strings = {
|
const strings = {
|
||||||
en: {
|
en: {
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
const test = require('node:test');
|
||||||
|
const assert = require('node:assert/strict');
|
||||||
|
const fs = require('node:fs');
|
||||||
|
const path = require('node:path');
|
||||||
|
const { pathToFileURL } = require('node:url');
|
||||||
|
|
||||||
|
const root = path.join(__dirname, '..');
|
||||||
|
const html = fs.readFileSync(path.join(root, 'index.html'), 'utf8');
|
||||||
|
|
||||||
|
function resolve(dict, key) {
|
||||||
|
if (typeof dict[key] === 'string') return dict[key];
|
||||||
|
if (key.includes('.')) return key.split('.').reduce((value, part) => value?.[part], dict);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
test('every data-i18n key in index.html exists in Thai and English', async () => {
|
||||||
|
const { TRANSLATIONS } = await import(pathToFileURL(path.join(root, 'js/i18n.js')).href);
|
||||||
|
const keys = new Set();
|
||||||
|
const attrRe = /data-i18n(?:-placeholder|-title|-alt|-aria-label)?="([^"]+)"/g;
|
||||||
|
let match;
|
||||||
|
while ((match = attrRe.exec(html))) keys.add(match[1].trim());
|
||||||
|
|
||||||
|
assert.ok(keys.size > 300, 'index.html should expose a large translation surface');
|
||||||
|
|
||||||
|
for (const lang of ['th', 'en']) {
|
||||||
|
const missing = [...keys].filter((key) => {
|
||||||
|
const value = resolve(TRANSLATIONS[lang], key);
|
||||||
|
return typeof value !== 'string' || !value.trim();
|
||||||
|
});
|
||||||
|
assert.deepEqual(missing, [], `${lang} is missing data-i18n keys: ${missing.join(', ')}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('nested element and path dictionaries stay addressable from HTML', async () => {
|
||||||
|
const { TRANSLATIONS } = await import(pathToFileURL(path.join(root, 'js/i18n.js')).href);
|
||||||
|
for (const lang of ['th', 'en']) {
|
||||||
|
for (const key of ['elements.Fire', 'elements.Ice', 'elements.Imaginary', 'paths.Destruction', 'paths.Elation']) {
|
||||||
|
const value = resolve(TRANSLATIONS[lang], key);
|
||||||
|
assert.equal(typeof value, 'string', `${lang}.${key} must resolve`);
|
||||||
|
assert.ok(value.trim().length > 0, `${lang}.${key} must not be empty`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.equal(html.includes('data-i18n="Fire"'), false);
|
||||||
|
assert.equal(html.includes('data-i18n="elements.Fire"'), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('the shared theory-craft hint is translated', async () => {
|
||||||
|
const { TRANSLATIONS } = await import(pathToFileURL(path.join(root, 'js/i18n.js')).href);
|
||||||
|
for (const lang of ['th', 'en']) {
|
||||||
|
assert.equal(typeof TRANSLATIONS[lang].fireflyTheoryModeHint, 'string');
|
||||||
|
assert.ok(TRANSLATIONS[lang].fireflyTheoryModeHint.trim().length > 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in new issue
Block a user