Add FireflyGo sync mode, extra_data controls and Enka import

- js/modes.js: per-backend capability matrix (GaCy GO / FireflyGo / RobinSR)
- js/firefly.js: POST /sync payload builder + extra_data normaliser
- js/enka-import.js: enka.network -> FreeSR converter with merge/replace
- app.js: mode-aware UI, firefly transport, Enka import, extra_data form
- index.html: enable FireflyGo, add Enka import + FireflyGo controls cards
- i18n: Thai/English strings for every new label, message and error
- vercel.json: /api/enka/:uid rewrite; scripts/dev-server.cjs for local dev
This commit is contained in:
CAtlas0784 committed 2026-11-03 16:42:02 +07:00
1 parent 03fc1b82bb
commit 8eb519023a
17 files changed
+2174 -162

No files matched your search

+170 -26
View File
@@ -475,7 +475,7 @@ export const TRANSLATIONS = {
"tabPersistentGaC": "💾 จัดการเซฟ GaCy",
"tabPersistentFirefly": "👤 ผู้บุกเบิก & March 7th",
"badgePersistenceGaC": "GaCy: persistent.json (/api/persistent)",
"badgePersistenceFirefly": "FireflyGo: data-in-game.json & freesr-data.json",
"badgePersistenceFirefly": "FireflyGo: freesr-data.json (POST /sync)",
"badgePersistenceRobin": "RobinSR: freesr-data.json (/api/freesr)",
"lblLcSuperimpose": "Superimpose (ขัดเกลา)",
"lcPickerTitle": "🗡️ เลือกสวมใส่กรวยแสง (Light Cone)",
@@ -969,7 +969,7 @@ export const TRANSLATIONS = {
"tabPersistentGaC": "💾 GaCy Save Manager",
"tabPersistentFirefly": "👤 Trailblazer & March 7th",
"badgePersistenceGaC": "GaCy: persistent.json (/api/persistent)",
"badgePersistenceFirefly": "FireflyGo: data-in-game.json & freesr-data.json",
"badgePersistenceFirefly": "FireflyGo: freesr-data.json (POST /sync)",
"badgePersistenceRobin": "RobinSR: freesr-data.json (/api/freesr)",
"lblLcSuperimpose": "Superimpose Rank",
"lcPickerTitle": "🗡️ Select Light Cone to Equip",
@@ -1320,7 +1320,7 @@ export const TRANSLATIONS = {
"tabPersistentGaC": "💾 GaCy 存档管理",
"tabPersistentFirefly": "👤 开拓者与三月七",
"badgePersistenceGaC": "GaCy: persistent.json (/api/persistent)",
"badgePersistenceFirefly": "FireflyGo: data-in-game.json & freesr-data.json",
"badgePersistenceFirefly": "FireflyGo: freesr-data.json (POST /sync)",
"badgePersistenceRobin": "RobinSR: freesr-data.json (/api/freesr)",
"lblLcSuperimpose": "叠影等阶",
"lcPickerTitle": "🗡️ 选择要装备的光锥",
@@ -1670,7 +1670,7 @@ export const TRANSLATIONS = {
"tabPersistentGaC": "💾 GaCy 存檔管理",
"tabPersistentFirefly": "👤 開拓者與三月七",
"badgePersistenceGaC": "GaCy: persistent.json (/api/persistent)",
"badgePersistenceFirefly": "FireflyGo: data-in-game.json & freesr-data.json",
"badgePersistenceFirefly": "FireflyGo: freesr-data.json (POST /sync)",
"badgePersistenceRobin": "RobinSR: freesr-data.json (/api/freesr)",
"lblLcSuperimpose": "疊影等階",
"lcPickerTitle": "🗡️ 選擇要裝備的光錐",
@@ -2020,7 +2020,7 @@ export const TRANSLATIONS = {
"tabPersistentGaC": "💾 GaCyセーブデータ管理",
"tabPersistentFirefly": "👤 開拓者&三月なのか",
"badgePersistenceGaC": "GaCy: persistent.json (/api/persistent)",
"badgePersistenceFirefly": "FireflyGo: data-in-game.json & freesr-data.json",
"badgePersistenceFirefly": "FireflyGo: freesr-data.json (POST /sync)",
"badgePersistenceRobin": "RobinSR: freesr-data.json (/api/freesr)",
"lblLcSuperimpose": "重畳ランク",
"lcPickerTitle": "🗡️ 装備する光円錐を選択",
@@ -2370,7 +2370,7 @@ export const TRANSLATIONS = {
"tabPersistentGaC": "💾 GaCy 세이브 관리",
"tabPersistentFirefly": "👤 개척자 & March 7th",
"badgePersistenceGaC": "GaCy: persistent.json (/api/persistent)",
"badgePersistenceFirefly": "FireflyGo: data-in-game.json & freesr-data.json",
"badgePersistenceFirefly": "FireflyGo: freesr-data.json (POST /sync)",
"badgePersistenceRobin": "RobinSR: freesr-data.json (/api/freesr)",
"lblLcSuperimpose": "중첩 등급",
"lcPickerTitle": "🗡️ 장착할 광추 선택",
@@ -2720,7 +2720,7 @@ export const TRANSLATIONS = {
"tabPersistentGaC": "💾 Quản lý lưu GaCy",
"tabPersistentFirefly": "👤 Nhà Khai Phá & March 7th",
"badgePersistenceGaC": "GaCy: persistent.json (/api/persistent)",
"badgePersistenceFirefly": "FireflyGo: data-in-game.json & freesr-data.json",
"badgePersistenceFirefly": "FireflyGo: freesr-data.json (POST /sync)",
"badgePersistenceRobin": "RobinSR: freesr-data.json (/api/freesr)",
"lblLcSuperimpose": "Bậc Tích Lũy",
"lcPickerTitle": "🗡️ Chọn Nón Ánh Sáng để trang bị",
@@ -3070,7 +3070,7 @@ export const TRANSLATIONS = {
"tabPersistentGaC": "💾 Pengelola Simpan GaCy",
"tabPersistentFirefly": "👤 Trailblazer & March 7th",
"badgePersistenceGaC": "GaCy: persistent.json (/api/persistent)",
"badgePersistenceFirefly": "FireflyGo: data-in-game.json & freesr-data.json",
"badgePersistenceFirefly": "FireflyGo: freesr-data.json (POST /sync)",
"badgePersistenceRobin": "RobinSR: freesr-data.json (/api/freesr)",
"lblLcSuperimpose": "Tingkat Superimpose",
"lcPickerTitle": "🗡️ Pilih Light Cone untuk Dipasang",
@@ -3420,7 +3420,7 @@ export const TRANSLATIONS = {
"tabPersistentGaC": "💾 Gestor de guardado GaCy",
"tabPersistentFirefly": "👤 Trazacaminos y Siete de Marzo",
"badgePersistenceGaC": "GaCy: persistent.json (/api/persistent)",
"badgePersistenceFirefly": "FireflyGo: data-in-game.json & freesr-data.json",
"badgePersistenceFirefly": "FireflyGo: freesr-data.json (POST /sync)",
"badgePersistenceRobin": "RobinSR: freesr-data.json (/api/freesr)",
"lblLcSuperimpose": "Rango de superposición",
"lcPickerTitle": "🗡️ Seleccionar Cono de Luz para equipar",
@@ -3770,7 +3770,7 @@ export const TRANSLATIONS = {
"tabPersistentGaC": "💾 Gestionnaire de sauvegarde GaCy",
"tabPersistentFirefly": "👤 Pionnier & March 7th",
"badgePersistenceGaC": "GaCy: persistent.json (/api/persistent)",
"badgePersistenceFirefly": "FireflyGo: data-in-game.json & freesr-data.json",
"badgePersistenceFirefly": "FireflyGo: freesr-data.json (POST /sync)",
"badgePersistenceRobin": "RobinSR: freesr-data.json (/api/freesr)",
"lblLcSuperimpose": "Rang de superposition",
"lcPickerTitle": "🗡️ Sélectionner un Cône de Lumière à équiper",
@@ -4120,7 +4120,7 @@ export const TRANSLATIONS = {
"tabPersistentGaC": "💾 GaCy-Speicherverwaltung",
"tabPersistentFirefly": "👤 Trailblazer & March 7th",
"badgePersistenceGaC": "GaCy: persistent.json (/api/persistent)",
"badgePersistenceFirefly": "FireflyGo: data-in-game.json & freesr-data.json",
"badgePersistenceFirefly": "FireflyGo: freesr-data.json (POST /sync)",
"badgePersistenceRobin": "RobinSR: freesr-data.json (/api/freesr)",
"lblLcSuperimpose": "Überlagerungsrang",
"lcPickerTitle": "🗡️ Lichtkegel zum Ausrüsten wählen",
@@ -4470,7 +4470,7 @@ export const TRANSLATIONS = {
"tabPersistentGaC": "💾 Управление сохранениями GaCy",
"tabPersistentFirefly": "👤 Первопроходец и Март 7",
"badgePersistenceGaC": "GaCy: persistent.json (/api/persistent)",
"badgePersistenceFirefly": "FireflyGo: data-in-game.json & freesr-data.json",
"badgePersistenceFirefly": "FireflyGo: freesr-data.json (POST /sync)",
"badgePersistenceRobin": "RobinSR: freesr-data.json (/api/freesr)",
"lblLcSuperimpose": "Ранг наложения",
"lcPickerTitle": "🗡️ Выберите Световой конус для экипировки",
@@ -4820,7 +4820,7 @@ export const TRANSLATIONS = {
"tabPersistentGaC": "💾 Gerenciador de Saves GaCy",
"tabPersistentFirefly": "👤 Desbravador e March 7th",
"badgePersistenceGaC": "GaCy: persistent.json (/api/persistent)",
"badgePersistenceFirefly": "FireflyGo: data-in-game.json & freesr-data.json",
"badgePersistenceFirefly": "FireflyGo: freesr-data.json (POST /sync)",
"badgePersistenceRobin": "RobinSR: freesr-data.json (/api/freesr)",
"lblLcSuperimpose": "Classificação de Sobreposição",
"lcPickerTitle": "🗡️ Selecionar Cone de Luz para Equipar",
@@ -6826,19 +6826,19 @@ for (const [language, label] of Object.entries(MONSTER_PICKER_TRANSLATIONS)) {
}
const SERVER_MODE_AVAILABILITY_TRANSLATIONS = {
th: { serverModeFireflyPaused: 'FireflyGo — กำลังพัฒนา', serverModeRobinPaused: 'RobinSR — กำลังพัฒนา', serverModesPausedNotice: 'FireflyGo และ RobinSR ปิดใช้งานชั่วคราวระหว่างพัฒนา จึงกลับไปใช้ GaC' },
en: { serverModeFireflyPaused: 'FireflyGo — Under development', serverModeRobinPaused: 'RobinSR — Under development', serverModesPausedNotice: 'FireflyGo and RobinSR are temporarily disabled during development. Switched back to GaC.' },
'zh-CN': { serverModeFireflyPaused: 'FireflyGo — 开发中', serverModeRobinPaused: 'RobinSR — 开发中', serverModesPausedNotice: 'FireflyGo 和 RobinSR 正在开发中,暂时停用。已切回 GaCy。' },
'zh-TW': { serverModeFireflyPaused: 'FireflyGo — 開發中', serverModeRobinPaused: 'RobinSR — 開發中', serverModesPausedNotice: 'FireflyGo 和 RobinSR 正在開發中,暫時停用。已切回 GaCy。' },
ja: { serverModeFireflyPaused: 'FireflyGo — 開発中', serverModeRobinPaused: 'RobinSR — 開発中', serverModesPausedNotice: 'FireflyGo と RobinSR は開発中のため一時停止しています。GaCy に切り替えました。' },
ko: { serverModeFireflyPaused: 'FireflyGo — 개발 중', serverModeRobinPaused: 'RobinSR — 개발 중', serverModesPausedNotice: 'FireflyGo와 RobinSR은 개발 중이라 일시적으로 비활성화되었습니다. GaCy로 전환했습니다.' },
vi: { serverModeFireflyPaused: 'FireflyGo — Đang phát triển', serverModeRobinPaused: 'RobinSR — Đang phát triển', serverModesPausedNotice: 'FireflyGo và RobinSR đang được phát triển nên tạm thời bị tắt. Đã chuyển về GaCy.' },
id: { serverModeFireflyPaused: 'FireflyGo — Sedang dikembangkan', serverModeRobinPaused: 'RobinSR — Sedang dikembangkan', serverModesPausedNotice: 'FireflyGo dan RobinSR dinonaktifkan sementara selama pengembangan. Kembali ke GaCy.' },
es: { serverModeFireflyPaused: 'FireflyGo — En desarrollo', serverModeRobinPaused: 'RobinSR — En desarrollo', serverModesPausedNotice: 'FireflyGo y RobinSR están desactivados temporalmente durante su desarrollo. Se cambió a GaCy.' },
fr: { serverModeFireflyPaused: 'FireflyGo — En développement', serverModeRobinPaused: 'RobinSR — En développement', serverModesPausedNotice: 'FireflyGo et RobinSR sont temporairement désactivés pendant leur développement. Retour à GaCy.' },
de: { serverModeFireflyPaused: 'FireflyGo — In Entwicklung', serverModeRobinPaused: 'RobinSR — In Entwicklung', serverModesPausedNotice: 'FireflyGo und RobinSR sind während der Entwicklung vorübergehend deaktiviert. Zu GaCy gewechselt.' },
ru: { serverModeFireflyPaused: 'FireflyGo — В разработке', serverModeRobinPaused: 'RobinSR — В разработке', serverModesPausedNotice: 'FireflyGo и RobinSR временно отключены на время разработки. Выполнен переход на GaCy.' },
pt: { serverModeFireflyPaused: 'FireflyGo — Em desenvolvimento', serverModeRobinPaused: 'RobinSR — Em desenvolvimento', serverModesPausedNotice: 'FireflyGo e RobinSR estão temporariamente desativados durante o desenvolvimento. Voltou para GaCy.' }
th: { serverModeFireflyPaused: 'FireflyGo — กำลังพัฒนา', serverModeRobinPaused: 'RobinSR — กำลังพัฒนา' },
en: { serverModeFireflyPaused: 'FireflyGo — Under development', serverModeRobinPaused: 'RobinSR — Under development' },
'zh-CN': { serverModeFireflyPaused: 'FireflyGo — 开发中', serverModeRobinPaused: 'RobinSR — 开发中' },
'zh-TW': { serverModeFireflyPaused: 'FireflyGo — 開發中', serverModeRobinPaused: 'RobinSR — 開發中' },
ja: { serverModeFireflyPaused: 'FireflyGo — 開発中', serverModeRobinPaused: 'RobinSR — 開発中' },
ko: { serverModeFireflyPaused: 'FireflyGo — 개발 중', serverModeRobinPaused: 'RobinSR — 개발 중' },
vi: { serverModeFireflyPaused: 'FireflyGo — Đang phát triển', serverModeRobinPaused: 'RobinSR — Đang phát triển' },
id: { serverModeFireflyPaused: 'FireflyGo — Sedang dikembangkan', serverModeRobinPaused: 'RobinSR — Sedang dikembangkan' },
es: { serverModeFireflyPaused: 'FireflyGo — En desarrollo', serverModeRobinPaused: 'RobinSR — En desarrollo' },
fr: { serverModeFireflyPaused: 'FireflyGo — En développement', serverModeRobinPaused: 'RobinSR — En développement' },
de: { serverModeFireflyPaused: 'FireflyGo — In Entwicklung', serverModeRobinPaused: 'RobinSR — In Entwicklung' },
ru: { serverModeFireflyPaused: 'FireflyGo — В разработке', serverModeRobinPaused: 'RobinSR — В разработке' },
pt: { serverModeFireflyPaused: 'FireflyGo — Em desenvolvimento', serverModeRobinPaused: 'RobinSR — Em desenvolvimento' }
};
for (const [language, additions] of Object.entries(ADDITIONAL_TRANSLATIONS)) {
@@ -7049,6 +7049,78 @@ for (const [language, description] of Object.entries(ITEM_CATALOG_INTERACTION_DE
// language falls back to en through t(), so no Thai leaks into other locales.
const MODAL_AND_TOOL_TRANSLATIONS = {
th: {
// Server modes
serverModeFirefly: 'FireflyGo',
apiUrlHintGaC: 'GaCy GO ใช้ REST API ใต้ URL นี้ (เช่น /api/status, /api/freesr, /api/persistent)',
apiUrlHintFirefly: 'FireflyGo รับข้อมูลทาง POST <URL นี้>/sync เท่านั้น — ต้องเปิดเซิร์ฟเวอร์ Firefly_Srtools ไว้ที่เครื่องเดียวกัน',
apiUrlHintRobin: 'RobinSR ยังไม่รองรับในเวอร์ชันนี้',
// Enka import
enkaImportTitle: '📡 สร้างไฟล์ FreeSR จาก UID เกมจริง (Enka)',
enkaImportSubtitle: 'ดึงตัวละคร กรวยแสง และรีลิกส์จากโปรไฟล์ Enka แล้วสร้างเป็นไฟล์ freesr-data.json ใช้ได้ทุกโหมดการเชื่อมต่อ',
enkaUidLabel: 'UID ของเกม',
enkaUidPlaceholder: '800000000',
enkaUidInvalid: 'UID ไม่ถูกต้อง ต้องเป็นตัวเลข 8-10 หลัก',
enkaModeMerge: 'รวมกับข้อมูลเดิม',
enkaModeReplace: 'แทนที่ตัวละครทั้งหมด',
btnEnkaFetch: 'ดึงข้อมูลจาก Enka',
enkaPasteLabel: 'หรือวาง JSON จาก Enka',
enkaPastePlaceholder: 'https://enka.network/api/hsr/uid/...',
btnEnkaParsePaste: 'ใช้ JSON ที่วาง',
enkaFetching: 'กำลังดึงข้อมูล UID {uid}...',
enkaImportDone: 'นำเข้าสำเร็จ: ตัวละคร {avatars} • กรวยแสง {lightcones} • รีลิกส์ {relics}',
enkaUidNotFound: 'ไม่พบ UID นี้ใน Enka (หรือโปรไฟล์ถูกตั้งเป็นส่วนตัว)',
enkaRateLimited: 'Enka จำกัดจำนวนการเรียก กรุณารอสักครู่แล้วลองใหม่',
enkaFetchFailed: 'ดึงข้อมูลจาก Enka ไม่สำเร็จ (HTTP {status})',
enkaFetchFailedDetail: 'นำเข้าไม่สำเร็จ: {message}',
enkaNoAvatars: 'ข้อมูลนี้ไม่มีตัวละครที่แสดงอยู่ (โปรไฟล์อาจถูกซ่อน)',
enkaPasteEmpty: 'ยังไม่มี JSON ที่วางไว้',
enkaPasteInvalid: 'JSON ที่วางไม่ถูกต้อง',
enkaProxyUnavailable: 'เรียก Enka ไม่ได้ — ตรวจสอบว่าเว็บนี้มี proxy /api/enka หรือใช้ช่องวาง JSON แทน',
enkaSyncFailed: 'นำเข้าในเครื่องแล้ว แต่ส่งไปเซิร์ฟเวอร์ไม่สำเร็จ: {message}',
// FireflyGo extra_data
fireflyExtrasTitle: '🦋 ตัวควบคุม FireflyGo (extra_data)',
fireflyExtrasBadge: 'POST /sync',
fireflyExtrasSubtitle: 'ค่าเหล่านี้ถูกส่งไปพร้อมข้อมูลตัวละครทุกครั้งที่ซิงค์ เพื่อสั่งงานสคริปต์และเซิร์ฟเวอร์ Firefly',
fireflyMultiPathTitle: '🧭 Multi-Path (Trailblazer)',
fireflyMultiPathMain: 'Path id หลัก',
fireflyMultiPathMarch7: 'Path id ของ March 7th',
fireflyMultiPathMainList: 'รายการ Path หลัก',
fireflyMultiPathMarch7List: 'รายการ Path ของ March 7th',
fireflySettingTitle: '🎛️ ตั้งค่าในเกม',
fireflySettingCensorship: 'Censorship',
fireflySettingCm: 'Cinematic mode',
fireflySettingFirstPerson: 'มุมมองบุคคลที่หนึ่ง',
fireflySettingHideUi: 'ซ่อน UI',
fireflySettingInvasion: 'เปอร์เซ็นต์การบุกรุก',
fireflyChallengeTitle: '⚔️ Challenge Peak',
fireflyChallengeSkipNode: 'ข้ามโหนด',
fireflyChallengeGroupId: 'Peak group id',
fireflyChallengeGroupList: 'รายการ Peak group id',
fireflyTheoryTitle: '🧪 Theory Craft',
fireflyTheoryMode: 'เปิดโหมด Theory Craft',
fireflyTheoryCycleCount: 'จำนวนรอบ',
fireflyTheoryStageId: 'Stage id',
fireflyTheoryLineup: 'ทีมที่กำหนดเอง',
fireflyTheoryHp: 'ค่า HP ทับ (JSON)',
fireflyLuaLabel: 'สคริปต์ Lua (ไม่บังคับ)',
fireflyLuaPlaceholder: '-- lua ที่กำหนดเอง',
fireflyListPlaceholder: '1, 2, 3',
btnFireflyProbe: '🔄 ดึงค่าจากเซิร์ฟเวอร์',
btnFireflySaveExtra: '💾 บันทึกตัวควบคุม',
btnFireflySync: '🚀 ซิงค์ลง FireflyGo',
fireflyProbing: 'กำลังเชื่อมต่อ FireflyGo...',
fireflySyncing: 'กำลังส่งข้อมูลไปยัง FireflyGo...',
fireflyProbeSuccess: 'เชื่อมต่อ FireflyGo สำเร็จ',
fireflySyncSuccess: 'ซิงค์ข้อมูลลง FireflyGo สำเร็จ',
fireflyRequestFailed: 'FireflyGo ตอบกลับด้วยข้อผิดพลาด',
fireflyRequestFailedDetail: 'ไม่สำเร็จ: {message}',
fireflyTimeout: 'FireflyGo ไม่ตอบสนอง (หมดเวลา)',
fireflyNoData: 'ยังไม่มีข้อมูลตัวละครให้ซิงค์',
fireflyExtraSaved: 'บันทึกตัวควบคุม FireflyGo แล้ว',
fireflyHpInvalid: 'ค่า HP ต้องเป็น JSON object เช่น {"1001": [12000, 9000]}',
assignPickerTitleRelic: 'สวมใส่รีลิกส์ให้ตัวละคร',
assignPickerTitleLc: 'สวมใส่กรวยแสงให้ตัวละคร',
assignPickerSubtitle: 'เลือกตัวละครที่จะสวมใส่ {item} — หรือเก็บไว้ในคลัง',
@@ -7184,6 +7256,78 @@ const MODAL_AND_TOOL_TRANSLATIONS = {
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'
},
en: {
// Server modes
serverModeFirefly: 'FireflyGo',
apiUrlHintGaC: 'GaCy GO serves its REST API under this URL (e.g. /api/status, /api/freesr, /api/persistent)',
apiUrlHintFirefly: 'FireflyGo only accepts POST <this URL>/sync — it must be the machine running Firefly_Srtools',
apiUrlHintRobin: 'RobinSR is not supported in this build yet',
// Enka import
enkaImportTitle: '📡 Build a FreeSR file from a real game UID (Enka)',
enkaImportSubtitle: 'Pull characters, light cones and relics from an Enka profile and turn them into freesr-data.json. Works in every connection mode.',
enkaUidLabel: 'Game UID',
enkaUidPlaceholder: '800000000',
enkaUidInvalid: 'Invalid UID — it must be 8-10 digits',
enkaModeMerge: 'Merge with existing data',
enkaModeReplace: 'Replace every character',
btnEnkaFetch: 'Fetch from Enka',
enkaPasteLabel: 'Or paste the Enka JSON',
enkaPastePlaceholder: 'https://enka.network/api/hsr/uid/...',
btnEnkaParsePaste: 'Use the pasted JSON',
enkaFetching: 'Fetching UID {uid}...',
enkaImportDone: 'Imported: {avatars} characters • {lightcones} light cones • {relics} relics',
enkaUidNotFound: 'That UID was not found on Enka (or the profile is private)',
enkaRateLimited: 'Enka is rate limiting requests. Please wait a moment and try again.',
enkaFetchFailed: 'Could not fetch from Enka (HTTP {status})',
enkaFetchFailedDetail: 'Import failed: {message}',
enkaNoAvatars: 'This payload has no visible characters (the profile may be hidden)',
enkaPasteEmpty: 'There is no pasted JSON yet',
enkaPasteInvalid: 'The pasted JSON is not valid',
enkaProxyUnavailable: 'Cannot reach Enka — check that this site exposes the /api/enka proxy, or use the paste field instead',
enkaSyncFailed: 'Imported locally, but sending it to the server failed: {message}',
// FireflyGo extra_data
fireflyExtrasTitle: '🦋 FireflyGo controls (extra_data)',
fireflyExtrasBadge: 'POST /sync',
fireflyExtrasSubtitle: 'These values are sent with the character data on every sync to drive the Firefly script and server.',
fireflyMultiPathTitle: '🧭 Multi-Path (Trailblazer)',
fireflyMultiPathMain: 'Main path id',
fireflyMultiPathMarch7: 'March 7th path id',
fireflyMultiPathMainList: 'Main path list',
fireflyMultiPathMarch7List: 'March 7th path list',
fireflySettingTitle: '🎛️ In-game settings',
fireflySettingCensorship: 'Censorship',
fireflySettingCm: 'Cinematic mode',
fireflySettingFirstPerson: 'First person',
fireflySettingHideUi: 'Hide UI',
fireflySettingInvasion: 'Invasion percent',
fireflyChallengeTitle: '⚔️ Challenge Peak',
fireflyChallengeSkipNode: 'Skip node',
fireflyChallengeGroupId: 'Peak group id',
fireflyChallengeGroupList: 'Peak group id list',
fireflyTheoryTitle: '🧪 Theory Craft',
fireflyTheoryMode: 'Enable theory craft',
fireflyTheoryCycleCount: 'Cycle count',
fireflyTheoryStageId: 'Stage id',
fireflyTheoryLineup: 'Custom lineup',
fireflyTheoryHp: 'HP overrides (JSON)',
fireflyLuaLabel: 'Lua script (optional)',
fireflyLuaPlaceholder: '-- custom lua',
fireflyListPlaceholder: '1, 2, 3',
btnFireflyProbe: '🔄 Pull values from server',
btnFireflySaveExtra: '💾 Save controls',
btnFireflySync: '🚀 Sync to FireflyGo',
fireflyProbing: 'Connecting to FireflyGo...',
fireflySyncing: 'Sending data to FireflyGo...',
fireflyProbeSuccess: 'Connected to FireflyGo',
fireflySyncSuccess: 'Synced to FireflyGo',
fireflyRequestFailed: 'FireflyGo returned an error',
fireflyRequestFailedDetail: 'Failed: {message}',
fireflyTimeout: 'FireflyGo did not respond (timed out)',
fireflyNoData: 'There is no character data to sync yet',
fireflyExtraSaved: 'FireflyGo controls saved',
fireflyHpInvalid: 'HP overrides must be a JSON object such as {"1001": [12000, 9000]}',
assignPickerTitleRelic: 'Equip Relic to a Character',
assignPickerTitleLc: 'Equip Light Cone to a Character',
assignPickerSubtitle: 'Choose who wears {item} — or keep it in your inventory',