From 4ce47dc6d23e26cf9819e05f9fe1810a6f6481bb Mon Sep 17 00:00:00 2001 From: kitbyte Date: Mon, 15 Jun 2026 00:26:41 +0300 Subject: [PATCH] feat(web-panel): multi-locale i18n with selector + browser autodetect - Add 6 locales (en-US source + ru-RU, de-DE, fr-FR, es-ES, zh-CN) matching the patcher's WPF UI; full .po catalogs incl. plural forms. - Language selector in the left settings drawer; persist choice and auto-detect from navigator language on first load. - Load .po directly via @lingui/vite-plugin (drop the compile step); gitignore generated catalog .js as build artifacts. --- .gitattributes | 4 + web-panel/.gitignore | 4 + web-panel/lingui.config.ts | 4 +- web-panel/package.json | 2 +- web-panel/src/app/i18n.ts | 74 +++- web-panel/src/app/main.tsx | 4 +- web-panel/src/app/ui/SettingsDrawer.tsx | 30 ++ web-panel/src/locales/de-DE/messages.po | 345 ++++++++++++++++++ .../src/locales/{en => en-US}/messages.po | 4 + web-panel/src/locales/en/messages.js | 1 - web-panel/src/locales/es-ES/messages.po | 345 ++++++++++++++++++ web-panel/src/locales/fr-FR/messages.po | 345 ++++++++++++++++++ web-panel/src/locales/ru-RU/messages.po | 345 ++++++++++++++++++ web-panel/src/locales/zh-CN/messages.po | 345 ++++++++++++++++++ 14 files changed, 1831 insertions(+), 21 deletions(-) create mode 100644 .gitattributes create mode 100644 web-panel/src/locales/de-DE/messages.po rename web-panel/src/locales/{en => en-US}/messages.po (99%) delete mode 100644 web-panel/src/locales/en/messages.js create mode 100644 web-panel/src/locales/es-ES/messages.po create mode 100644 web-panel/src/locales/fr-FR/messages.po create mode 100644 web-panel/src/locales/ru-RU/messages.po create mode 100644 web-panel/src/locales/zh-CN/messages.po diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3c72233 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# The web panel is the bundled frontend shipped inside the C# patcher. +# Mark it as vendored so GitHub Linguist keeps it out of the repository's +# language statistics — the project is a C# app, not a TypeScript one. +web-panel/** linguist-vendored diff --git a/web-panel/.gitignore b/web-panel/.gitignore index a547bf3..478e171 100644 --- a/web-panel/.gitignore +++ b/web-panel/.gitignore @@ -22,3 +22,7 @@ dist-ssr *.njsproj *.sln *.sw? + +# Compiled lingui catalogs — generated from .po by `lingui compile`; the app +# loads .po directly via @lingui/vite-plugin, so these are build artifacts. +src/locales/**/*.js diff --git a/web-panel/lingui.config.ts b/web-panel/lingui.config.ts index bba377b..d266e80 100644 --- a/web-panel/lingui.config.ts +++ b/web-panel/lingui.config.ts @@ -2,8 +2,8 @@ import { defineConfig } from '@lingui/cli'; import { formatter } from '@lingui/format-po'; export default defineConfig({ - sourceLocale: 'en', - locales: ['en'], + sourceLocale: 'en-US', + locales: ['en-US', 'ru-RU', 'de-DE', 'fr-FR', 'es-ES', 'zh-CN'], catalogs: [ { path: '/src/locales/{locale}/messages', diff --git a/web-panel/package.json b/web-panel/package.json index 02a64e2..1daad76 100644 --- a/web-panel/package.json +++ b/web-panel/package.json @@ -6,7 +6,7 @@ "scripts": { "dev": "vite", "dev:host": "vite --host 0.0.0.0", - "build": "pnpm run i18n:compile && tsc --noEmit && vite build && pnpm run build:bridge", + "build": "tsc --noEmit && vite build && pnpm run build:bridge", "build:bridge": "node ./bridge/build.mjs", "lint": "eslint src protocol bridge/src --max-warnings=0", "typecheck:web": "tsc --noEmit", diff --git a/web-panel/src/app/i18n.ts b/web-panel/src/app/i18n.ts index 7cc4a82..224cdd2 100644 --- a/web-panel/src/app/i18n.ts +++ b/web-panel/src/app/i18n.ts @@ -1,26 +1,70 @@ -import { i18n } from '@lingui/core'; +import { i18n, type Messages } from '@lingui/core'; -export const DEFAULT_LOCALE = 'en'; +export const DEFAULT_LOCALE = 'en-US'; -type CatalogModule = { - default?: { messages: Record }; - messages?: Record; -}; +export const SUPPORTED_LOCALES = [ + { code: 'en-US', label: 'English' }, + { code: 'ru-RU', label: 'Русский' }, + { code: 'de-DE', label: 'Deutsch' }, + { code: 'fr-FR', label: 'Français' }, + { code: 'es-ES', label: 'Español' }, + { code: 'zh-CN', label: '简体中文' }, +] as const; -const catalogs = import.meta.glob('../locales/*/messages.js'); +export type LocaleCode = (typeof SUPPORTED_LOCALES)[number]['code']; -export async function activateLocale(locale: string): Promise { - const loadCatalog = catalogs[`../locales/${locale}/messages.js`]; +const LOCALE_STORAGE_KEY = 'wand:locale'; + +type CatalogModule = { messages: Messages }; + +const catalogs = import.meta.glob('../locales/*/messages.po'); + +export async function activateLocale(locale: LocaleCode): Promise { + const loadCatalog = catalogs[`../locales/${locale}/messages.po`]; if (!loadCatalog) { throw new Error(`Locale catalog not found: ${locale}`); } - const catalog = await loadCatalog(); - const messages = catalog.messages ?? catalog.default?.messages; - if (!messages) { - throw new Error(`Locale catalog is invalid: ${locale}`); - } - + const { messages } = await loadCatalog(); i18n.load(locale, messages); i18n.activate(locale); + persistLocale(locale); +} + +export function detectInitialLocale(): LocaleCode { + return readStoredLocale() ?? matchBrowserLocale() ?? DEFAULT_LOCALE; +} + +function readStoredLocale(): LocaleCode | null { + try { + const stored = localStorage.getItem(LOCALE_STORAGE_KEY); + return isSupportedLocale(stored) ? stored : null; + } catch { + return null; + } +} + +function matchBrowserLocale(): LocaleCode | null { + const candidates = typeof navigator === 'undefined' ? [] : (navigator.languages ?? [navigator.language]); + for (const candidate of candidates) { + const base = candidate.split('-')[0]; + const match = SUPPORTED_LOCALES.find(({ code }) => code === candidate || code.split('-')[0] === base); + if (match) { + return match.code; + } + } + + return null; +} + +function persistLocale(locale: LocaleCode): void { + try { + localStorage.setItem(LOCALE_STORAGE_KEY, locale); + } catch { + // Ignore storage failures (private mode, blocked cookies, etc.). + } +} + +function isSupportedLocale(value: string | null): value is LocaleCode { + return value !== null && SUPPORTED_LOCALES.some(({ code }) => code === value); } diff --git a/web-panel/src/app/main.tsx b/web-panel/src/app/main.tsx index 8248e8e..993475a 100644 --- a/web-panel/src/app/main.tsx +++ b/web-panel/src/app/main.tsx @@ -6,7 +6,7 @@ import { I18nProvider } from '@lingui/react'; import { applySavedAccentColor } from '@/appearance/appearance-storage'; import { App } from './app'; -import { activateLocale, DEFAULT_LOCALE } from './i18n'; +import { activateLocale, detectInitialLocale } from './i18n'; import '../index.css'; const root = document.getElementById('root') ?? document.getElementById('app'); @@ -17,7 +17,7 @@ if (!root) { applySavedAccentColor(); -activateLocale(DEFAULT_LOCALE).then(() => { +activateLocale(detectInitialLocale()).then(() => { createRoot(root).render( diff --git a/web-panel/src/app/ui/SettingsDrawer.tsx b/web-panel/src/app/ui/SettingsDrawer.tsx index af358c8..a08749f 100644 --- a/web-panel/src/app/ui/SettingsDrawer.tsx +++ b/web-panel/src/app/ui/SettingsDrawer.tsx @@ -6,6 +6,7 @@ import { useLingui } from '@lingui/react'; import { Icon } from '@/shared/ui/Icon'; import { cn } from '@/shared/lib/ui'; +import { activateLocale, type LocaleCode, SUPPORTED_LOCALES } from '@/app/i18n'; import { DEFAULT_ACCENT_COLOR, loadAccentColor, setAccentColor } from '@/appearance/appearance-storage'; import type { LibraryGame } from '@/library/model/games'; import { EConnectionStatus } from '@/remote-session/remote-session.reducer'; @@ -71,6 +72,9 @@ export const SettingsDrawer = ({ + + + @@ -160,6 +164,32 @@ const SessionPanel = ({ currentGame, currentTrainer }: { currentGame: LibraryGam ); }; +const LanguagePicker = () => { + const { i18n } = useLingui(); + + const handleSelect = (locale: LocaleCode) => { + void activateLocale(locale); + }; + + return ( +
+ {SUPPORTED_LOCALES.map(({ code, label }) => { + const active = i18n.locale === code; + return ( + + ); + })} +
+ ); +}; + const AccentPicker = () => { const { _ } = useLingui(); const [current, setCurrent] = useState(loadAccentColor); diff --git a/web-panel/src/locales/de-DE/messages.po b/web-panel/src/locales/de-DE/messages.po new file mode 100644 index 0000000..c72c4a4 --- /dev/null +++ b/web-panel/src/locales/de-DE/messages.po @@ -0,0 +1,345 @@ +msgid "" +msgstr "" +"POT-Creation-Date: 2026-06-15 00:17+0300\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: @lingui/cli\n" +"Language: de-DE\n" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Plural-Forms: \n" + +#. placeholder {0}: games.length +#: src/library/ui/LibraryDrawer.tsx +msgid "{0, plural, one {# game detected} other {# games detected}}" +msgstr "{0, plural, one {# Spiel erkannt} other {# Spiele erkannt}}" + +#. placeholder {0}: trainer.totalVisibleCheats +#: src/app/app.tsx +msgid "{0} matches" +msgstr "{0} Treffer" + +#: src/trainer/ui/CategorySection.tsx +msgid "{cheatCount} mods" +msgstr "{cheatCount} Mods" + +#: src/trainer/ui/CategorySection.tsx +msgid "{cheatCount} mods · {enabledCount}/{toggleCount} on" +msgstr "{cheatCount} Mods · {enabledCount}/{toggleCount} an" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Accent Color" +msgstr "Akzentfarbe" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Active Session" +msgstr "Aktive Sitzung" + +#: src/trainer/ui/QuickActions.tsx +msgid "Add" +msgstr "Hinzufügen" + +#: src/trainer/ui/QuickActions.tsx +msgid "Add Preset" +msgstr "Preset hinzufügen" + +#: src/library/ui/LibraryDrawer.tsx +msgid "All Games" +msgstr "Alle Spiele" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Amber" +msgstr "Bernstein" + +#: src/trainer/controls/ActionButton.tsx +msgid "Apply" +msgstr "Anwenden" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Bridge" +msgstr "Bridge" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Bridge offline" +msgstr "Bridge offline" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Browse library" +msgstr "Bibliothek öffnen" + +#: src/trainer/ui/QuickActions.tsx +msgid "Cancel" +msgstr "Abbrechen" + +#: src/trainer/ui/category-labels.ts +msgid "Challenge" +msgstr "Herausforderung" + +#: src/trainer/ui/category-labels.ts +msgid "Character" +msgstr "Charakter" + +#: src/trainer/ui/category-labels.ts +msgid "Cheats" +msgstr "Cheats" + +#: src/shared/ui/SearchInput.tsx +msgid "Clear search" +msgstr "Suche leeren" + +#: src/shared/ui/Drawer.tsx +msgid "Close drawer" +msgstr "Leiste schließen" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Close library" +msgstr "Bibliothek schließen" + +#: src/trainer/ui/QuickActions.tsx +msgid "Close preset modal" +msgstr "Preset-Fenster schließen" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Close settings" +msgstr "Einstellungen schließen" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Cobalt" +msgstr "Kobalt" + +#: src/trainer/ui/category-labels.ts +msgid "Crafting" +msgstr "Handwerk" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Crimson" +msgstr "Karminrot" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Custom" +msgstr "Eigene" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Cyan" +msgstr "Cyan" + +#. placeholder {0}: preset.name +#: src/trainer/ui/QuickActions.tsx +msgid "Delete preset {0}" +msgstr "Preset {0} löschen" + +#. placeholder {0}: trainer.totalCheats +#: src/app/app.tsx +msgid "END · {0} MODS" +msgstr "ENDE · {0} MODS" + +#: src/trainer/ui/category-labels.ts +msgid "Enemies" +msgstr "Gegner" + +#: src/library/ui/LibraryDrawer.tsx +#: src/trainer/ui/TrainerHeader.tsx +msgid "Favorite game" +msgstr "Spiel favorisieren" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Favorites" +msgstr "Favoriten" + +#: src/trainer/ui/category-labels.ts +msgid "Game" +msgstr "Spiel" + +#: src/app/ui/SettingsDrawer.tsx +msgid "GO" +msgstr "START" + +#: src/app/ui/TopBar.tsx +msgid "Idle · no game" +msgstr "Inaktiv · kein Spiel" + +#: src/trainer/ui/category-labels.ts +msgid "Inventory" +msgstr "Inventar" + +#: src/trainer/ui/category-labels.ts +msgid "Items" +msgstr "Gegenstände" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Language" +msgstr "Sprache" + +#: src/app/ui/FloatingDock.tsx +#: src/library/ui/LibraryDrawer.tsx +msgid "Library" +msgstr "Bibliothek" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Lime" +msgstr "Limette" + +#: src/app/ui/StatusPill.tsx +msgid "LINKING" +msgstr "VERBINDET" + +#: src/app/ui/StatusPill.tsx +msgid "LIVE" +msgstr "LIVE" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Magenta" +msgstr "Magenta" + +#: src/trainer/ui/QuickActions.tsx +msgid "Name" +msgstr "Name" + +#: src/trainer/ui/QuickActions.tsx +msgid "New preset" +msgstr "Neues Preset" + +#: src/app/ui/SettingsDrawer.tsx +msgid "No active game session." +msgstr "Keine aktive Spielsitzung." + +#: src/app/ui/SessionPlaceholder.tsx +msgid "No game is running yet. Open the library and launch one to start tweaking." +msgstr "Es läuft noch kein Spiel. Öffnen Sie die Bibliothek und starten Sie eines, um loszulegen." + +#: src/library/ui/LibraryDrawer.tsx +msgid "No games match \"{query}\"" +msgstr "Keine Spiele für „{query}“" + +#. placeholder {0}: trainer.query +#: src/app/app.tsx +msgid "No mods match \"{0}\"" +msgstr "Keine Mods für „{0}“" + +#: src/trainer/controls/SelectionControl.tsx +msgid "No options" +msgstr "Keine Optionen" + +#: src/app/ui/FloatingDock.tsx +msgid "No session" +msgstr "Keine Sitzung" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Now Playing" +msgstr "Wird gespielt" + +#: src/app/ui/StatusPill.tsx +msgid "OFFLINE" +msgstr "OFFLINE" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Open Settings" +msgstr "Einstellungen öffnen" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Open Settings to point Wand at your trainer bridge over WebSocket." +msgstr "Öffnen Sie die Einstellungen, um Wand über WebSocket mit Ihrer Trainer-Bridge zu verbinden." + +#: src/trainer/ui/QuickActions.tsx +msgid "Panic Off" +msgstr "Alles aus" + +#: src/trainer/ui/category-labels.ts +msgid "Physics" +msgstr "Physik" + +#: src/trainer/ui/category-labels.ts +msgid "Pinned" +msgstr "Angeheftet" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Play" +msgstr "Spielen" + +#: src/trainer/ui/category-labels.ts +msgid "Player" +msgstr "Spieler" + +#: src/trainer/ui/QuickActions.tsx +msgid "Preset name" +msgstr "Preset-Name" + +#: src/library/ui/LibraryDrawer.tsx +#: src/trainer/ui/TrainerHeader.tsx +msgid "Remove favorite" +msgstr "Favorit entfernen" + +#: src/trainer/ui/category-labels.ts +msgid "Resources" +msgstr "Ressourcen" + +#: src/trainer/ui/QuickActions.tsx +msgid "Save" +msgstr "Speichern" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Search games" +msgstr "Spiele suchen" + +#: src/app/app.tsx +msgid "Search mods" +msgstr "Mods suchen" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Select a game" +msgstr "Spiel auswählen" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Session" +msgstr "Sitzung" + +#: src/app/ui/FloatingDock.tsx +#: src/app/ui/SettingsDrawer.tsx +#: src/app/ui/TopBar.tsx +msgid "Settings" +msgstr "Einstellungen" + +#: src/trainer/ui/category-labels.ts +msgid "Stats" +msgstr "Werte" + +#: src/app/ui/SettingsDrawer.tsx +msgid "STOP" +msgstr "STOPP" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Stop playing" +msgstr "Beenden" + +#: src/trainer/ui/category-labels.ts +msgid "Teleport" +msgstr "Teleport" + +#: src/trainer/ui/TrainerHeader.tsx +msgid "Trainer Active" +msgstr "Trainer aktiv" + +#: src/trainer/ui/category-labels.ts +msgid "Vehicles" +msgstr "Fahrzeuge" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Violet" +msgstr "Violett" + +#. placeholder {0}: WEB_CONTRACT.defaultRemotePort +#: src/app/ui/SettingsDrawer.tsx +msgid "wand remote · port {0}" +msgstr "wand remote · Port {0}" + +#: src/trainer/ui/category-labels.ts +msgid "Weapons" +msgstr "Waffen" + +#: src/trainer/ui/category-labels.ts +msgid "World" +msgstr "Welt" diff --git a/web-panel/src/locales/en/messages.po b/web-panel/src/locales/en-US/messages.po similarity index 99% rename from web-panel/src/locales/en/messages.po rename to web-panel/src/locales/en-US/messages.po index 4bfe34f..cd367bc 100644 --- a/web-panel/src/locales/en/messages.po +++ b/web-panel/src/locales/en-US/messages.po @@ -170,6 +170,10 @@ msgstr "Inventory" msgid "Items" msgstr "Items" +#: src/app/ui/SettingsDrawer.tsx +msgid "Language" +msgstr "Language" + #: src/app/ui/FloatingDock.tsx #: src/library/ui/LibraryDrawer.tsx msgid "Library" diff --git a/web-panel/src/locales/en/messages.js b/web-panel/src/locales/en/messages.js deleted file mode 100644 index 4ccdcfe..0000000 --- a/web-panel/src/locales/en/messages.js +++ /dev/null @@ -1 +0,0 @@ -/*eslint-disable*/module.exports={messages:JSON.parse("{\"0eyak2\":[\"Close preset modal\"],\"15SPG8\":[\"Stop playing\"],\"1uJlG9\":[\"Accent Color\"],\"29Hx9U\":[\"Stats\"],\"2MiXF-\":[\"No mods match \\\"\",[\"0\"],\"\\\"\"],\"4R8qoo\":[\"No games match \\\"\",[\"query\"],\"\\\"\"],\"5B_EbJ\":[\"OFFLINE\"],\"5Tsr0S\":[\"GO\"],\"5_DJAT\":[\"Delete preset \",[\"0\"]],\"6YtxFj\":[\"Name\"],\"7kV7X8\":[\"Idle · no game\"],\"8Tg_JR\":[\"Custom\"],\"8v0yqM\":[\"Weapons\"],\"9EqSGz\":[\"Lime\"],\"BzfzPK\":[\"Items\"],\"C_i4ng\":[\"Select a game\"],\"Cie1-b\":[\"Teleport\"],\"CqO9qC\":[\"Session\"],\"D1jeqs\":[\"No session\"],\"DB8zMK\":[\"Apply\"],\"DD0Fnh\":[\"LINKING\"],\"DlBKuz\":[\"Browse library\"],\"F37c1s\":[\"Open Settings\"],\"Hz-sxK\":[\"No options\"],\"J24FyN\":[\"Bridge\"],\"Jv26w1\":[\"Close drawer\"],\"LCXVTv\":[\"Cobalt\"],\"LZRTnY\":[\"Game\"],\"NWm6Qw\":[\"All Games\"],\"OkA8xh\":[\"Crafting\"],\"OzDccM\":[\"Bridge offline\"],\"QBOwbf\":[\"Close settings\"],\"T91vKp\":[\"Play\"],\"TvwYwN\":[\"Enemies\"],\"Tz0i8g\":[\"Settings\"],\"U3lTk6\":[\"Add Preset\"],\"Ul-m9L\":[\"Search games\"],\"V3MCts\":[\"Preset name\"],\"V8yTm6\":[\"Clear search\"],\"X9kySA\":[\"Favorites\"],\"Y9Da-w\":[\"Trainer Active\"],\"ZrsGjm\":[\"Inventory\"],\"aPk9_7\":[\"Panic Off\"],\"dEgA5A\":[\"Cancel\"],\"dMVx8s\":[\"New preset\"],\"e73uuf\":[\"Crimson\"],\"eedtPL\":[\"Violet\"],\"exYcTF\":[\"Library\"],\"fFwMZv\":[\"Cyan\"],\"fg3Xvh\":[\"Character\"],\"fpMs2Z\":[\"LIVE\"],\"garODz\":[\"Remove favorite\"],\"i5IWIg\":[\"Physics\"],\"iZWlw6\":[\"Challenge\"],\"isSRI0\":[\"Active Session\"],\"kJs53F\":[[\"0\"],\" matches\"],\"kNiQp6\":[\"Pinned\"],\"llTC8Z\":[\"END · \",[\"0\"],\" MODS\"],\"m16xKo\":[\"Add\"],\"nPRduv\":[\"Close library\"],\"nsI6F9\":[[\"cheatCount\"],\" mods · \",[\"enabledCount\"],\"/\",[\"toggleCount\"],\" on\"],\"pBpfre\":[\"Cheats\"],\"pipqSe\":[\"Now Playing\"],\"q1-iDP\":[\"Open Settings to point Wand at your trainer bridge over WebSocket.\"],\"q1I2y_\":[[\"0\",\"plural\",{\"one\":[\"#\",\" game detected\"],\"other\":[\"#\",\" games detected\"]}]],\"qSNzRg\":[\"wand remote · port \",[\"0\"]],\"qVkch9\":[\"No active game session.\"],\"qanr4_\":[\"Search mods\"],\"s-MGs7\":[\"Resources\"],\"s8OcrP\":[\"Vehicles\"],\"tfDRzk\":[\"Save\"],\"u4hZgR\":[\"Favorite game\"],\"uprOiC\":[\"Amber\"],\"v-jdqd\":[\"World\"],\"vRayGs\":[\"Player\"],\"vmwjgT\":[\"No game is running yet. Open the library and launch one to start tweaking.\"],\"vz5zAR\":[\"Magenta\"],\"wOM6pH\":[\"STOP\"],\"xVi7fK\":[[\"cheatCount\"],\" mods\"]}")}; \ No newline at end of file diff --git a/web-panel/src/locales/es-ES/messages.po b/web-panel/src/locales/es-ES/messages.po new file mode 100644 index 0000000..84eebf5 --- /dev/null +++ b/web-panel/src/locales/es-ES/messages.po @@ -0,0 +1,345 @@ +msgid "" +msgstr "" +"POT-Creation-Date: 2026-06-15 00:17+0300\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: @lingui/cli\n" +"Language: es-ES\n" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Plural-Forms: \n" + +#. placeholder {0}: games.length +#: src/library/ui/LibraryDrawer.tsx +msgid "{0, plural, one {# game detected} other {# games detected}}" +msgstr "{0, plural, one {# juego detectado} other {# juegos detectados}}" + +#. placeholder {0}: trainer.totalVisibleCheats +#: src/app/app.tsx +msgid "{0} matches" +msgstr "{0} coincidencias" + +#: src/trainer/ui/CategorySection.tsx +msgid "{cheatCount} mods" +msgstr "{cheatCount} mods" + +#: src/trainer/ui/CategorySection.tsx +msgid "{cheatCount} mods · {enabledCount}/{toggleCount} on" +msgstr "{cheatCount} mods · {enabledCount}/{toggleCount} activos" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Accent Color" +msgstr "Color de acento" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Active Session" +msgstr "Sesión activa" + +#: src/trainer/ui/QuickActions.tsx +msgid "Add" +msgstr "Añadir" + +#: src/trainer/ui/QuickActions.tsx +msgid "Add Preset" +msgstr "Añadir preajuste" + +#: src/library/ui/LibraryDrawer.tsx +msgid "All Games" +msgstr "Todos los juegos" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Amber" +msgstr "Ámbar" + +#: src/trainer/controls/ActionButton.tsx +msgid "Apply" +msgstr "Aplicar" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Bridge" +msgstr "Puente" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Bridge offline" +msgstr "Puente desconectado" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Browse library" +msgstr "Explorar biblioteca" + +#: src/trainer/ui/QuickActions.tsx +msgid "Cancel" +msgstr "Cancelar" + +#: src/trainer/ui/category-labels.ts +msgid "Challenge" +msgstr "Desafío" + +#: src/trainer/ui/category-labels.ts +msgid "Character" +msgstr "Personaje" + +#: src/trainer/ui/category-labels.ts +msgid "Cheats" +msgstr "Trucos" + +#: src/shared/ui/SearchInput.tsx +msgid "Clear search" +msgstr "Borrar búsqueda" + +#: src/shared/ui/Drawer.tsx +msgid "Close drawer" +msgstr "Cerrar panel" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Close library" +msgstr "Cerrar biblioteca" + +#: src/trainer/ui/QuickActions.tsx +msgid "Close preset modal" +msgstr "Cerrar ventana de preajuste" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Close settings" +msgstr "Cerrar ajustes" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Cobalt" +msgstr "Cobalto" + +#: src/trainer/ui/category-labels.ts +msgid "Crafting" +msgstr "Fabricación" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Crimson" +msgstr "Carmesí" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Custom" +msgstr "Personalizado" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Cyan" +msgstr "Cian" + +#. placeholder {0}: preset.name +#: src/trainer/ui/QuickActions.tsx +msgid "Delete preset {0}" +msgstr "Eliminar preajuste {0}" + +#. placeholder {0}: trainer.totalCheats +#: src/app/app.tsx +msgid "END · {0} MODS" +msgstr "FIN · {0} MODS" + +#: src/trainer/ui/category-labels.ts +msgid "Enemies" +msgstr "Enemigos" + +#: src/library/ui/LibraryDrawer.tsx +#: src/trainer/ui/TrainerHeader.tsx +msgid "Favorite game" +msgstr "Marcar favorito" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Favorites" +msgstr "Favoritos" + +#: src/trainer/ui/category-labels.ts +msgid "Game" +msgstr "Juego" + +#: src/app/ui/SettingsDrawer.tsx +msgid "GO" +msgstr "IR" + +#: src/app/ui/TopBar.tsx +msgid "Idle · no game" +msgstr "Inactivo · sin juego" + +#: src/trainer/ui/category-labels.ts +msgid "Inventory" +msgstr "Inventario" + +#: src/trainer/ui/category-labels.ts +msgid "Items" +msgstr "Objetos" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Language" +msgstr "Idioma" + +#: src/app/ui/FloatingDock.tsx +#: src/library/ui/LibraryDrawer.tsx +msgid "Library" +msgstr "Biblioteca" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Lime" +msgstr "Lima" + +#: src/app/ui/StatusPill.tsx +msgid "LINKING" +msgstr "CONECTANDO" + +#: src/app/ui/StatusPill.tsx +msgid "LIVE" +msgstr "EN VIVO" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Magenta" +msgstr "Magenta" + +#: src/trainer/ui/QuickActions.tsx +msgid "Name" +msgstr "Nombre" + +#: src/trainer/ui/QuickActions.tsx +msgid "New preset" +msgstr "Nuevo preajuste" + +#: src/app/ui/SettingsDrawer.tsx +msgid "No active game session." +msgstr "No hay sesión de juego activa." + +#: src/app/ui/SessionPlaceholder.tsx +msgid "No game is running yet. Open the library and launch one to start tweaking." +msgstr "Aún no hay ningún juego en marcha. Abre la biblioteca e inicia uno para empezar a ajustar." + +#: src/library/ui/LibraryDrawer.tsx +msgid "No games match \"{query}\"" +msgstr "Ningún juego coincide con «{query}»" + +#. placeholder {0}: trainer.query +#: src/app/app.tsx +msgid "No mods match \"{0}\"" +msgstr "Ningún mod coincide con «{0}»" + +#: src/trainer/controls/SelectionControl.tsx +msgid "No options" +msgstr "Sin opciones" + +#: src/app/ui/FloatingDock.tsx +msgid "No session" +msgstr "Sin sesión" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Now Playing" +msgstr "Jugando ahora" + +#: src/app/ui/StatusPill.tsx +msgid "OFFLINE" +msgstr "SIN CONEXIÓN" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Open Settings" +msgstr "Abrir ajustes" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Open Settings to point Wand at your trainer bridge over WebSocket." +msgstr "Abre los ajustes para conectar Wand con tu puente de trainer por WebSocket." + +#: src/trainer/ui/QuickActions.tsx +msgid "Panic Off" +msgstr "Apagar todo" + +#: src/trainer/ui/category-labels.ts +msgid "Physics" +msgstr "Física" + +#: src/trainer/ui/category-labels.ts +msgid "Pinned" +msgstr "Fijados" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Play" +msgstr "Jugar" + +#: src/trainer/ui/category-labels.ts +msgid "Player" +msgstr "Jugador" + +#: src/trainer/ui/QuickActions.tsx +msgid "Preset name" +msgstr "Nombre del preajuste" + +#: src/library/ui/LibraryDrawer.tsx +#: src/trainer/ui/TrainerHeader.tsx +msgid "Remove favorite" +msgstr "Quitar favorito" + +#: src/trainer/ui/category-labels.ts +msgid "Resources" +msgstr "Recursos" + +#: src/trainer/ui/QuickActions.tsx +msgid "Save" +msgstr "Guardar" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Search games" +msgstr "Buscar juegos" + +#: src/app/app.tsx +msgid "Search mods" +msgstr "Buscar mods" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Select a game" +msgstr "Elige un juego" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Session" +msgstr "Sesión" + +#: src/app/ui/FloatingDock.tsx +#: src/app/ui/SettingsDrawer.tsx +#: src/app/ui/TopBar.tsx +msgid "Settings" +msgstr "Ajustes" + +#: src/trainer/ui/category-labels.ts +msgid "Stats" +msgstr "Estadísticas" + +#: src/app/ui/SettingsDrawer.tsx +msgid "STOP" +msgstr "PARAR" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Stop playing" +msgstr "Detener" + +#: src/trainer/ui/category-labels.ts +msgid "Teleport" +msgstr "Teletransporte" + +#: src/trainer/ui/TrainerHeader.tsx +msgid "Trainer Active" +msgstr "Trainer activo" + +#: src/trainer/ui/category-labels.ts +msgid "Vehicles" +msgstr "Vehículos" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Violet" +msgstr "Violeta" + +#. placeholder {0}: WEB_CONTRACT.defaultRemotePort +#: src/app/ui/SettingsDrawer.tsx +msgid "wand remote · port {0}" +msgstr "wand remote · puerto {0}" + +#: src/trainer/ui/category-labels.ts +msgid "Weapons" +msgstr "Armas" + +#: src/trainer/ui/category-labels.ts +msgid "World" +msgstr "Mundo" diff --git a/web-panel/src/locales/fr-FR/messages.po b/web-panel/src/locales/fr-FR/messages.po new file mode 100644 index 0000000..086b8e8 --- /dev/null +++ b/web-panel/src/locales/fr-FR/messages.po @@ -0,0 +1,345 @@ +msgid "" +msgstr "" +"POT-Creation-Date: 2026-06-15 00:17+0300\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: @lingui/cli\n" +"Language: fr-FR\n" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Plural-Forms: \n" + +#. placeholder {0}: games.length +#: src/library/ui/LibraryDrawer.tsx +msgid "{0, plural, one {# game detected} other {# games detected}}" +msgstr "{0, plural, one {# jeu détecté} other {# jeux détectés}}" + +#. placeholder {0}: trainer.totalVisibleCheats +#: src/app/app.tsx +msgid "{0} matches" +msgstr "{0} résultats" + +#: src/trainer/ui/CategorySection.tsx +msgid "{cheatCount} mods" +msgstr "{cheatCount} mods" + +#: src/trainer/ui/CategorySection.tsx +msgid "{cheatCount} mods · {enabledCount}/{toggleCount} on" +msgstr "{cheatCount} mods · {enabledCount}/{toggleCount} actifs" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Accent Color" +msgstr "Couleur d'accent" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Active Session" +msgstr "Session active" + +#: src/trainer/ui/QuickActions.tsx +msgid "Add" +msgstr "Ajouter" + +#: src/trainer/ui/QuickActions.tsx +msgid "Add Preset" +msgstr "Ajouter un préréglage" + +#: src/library/ui/LibraryDrawer.tsx +msgid "All Games" +msgstr "Tous les jeux" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Amber" +msgstr "Ambre" + +#: src/trainer/controls/ActionButton.tsx +msgid "Apply" +msgstr "Appliquer" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Bridge" +msgstr "Pont" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Bridge offline" +msgstr "Pont hors ligne" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Browse library" +msgstr "Parcourir la bibliothèque" + +#: src/trainer/ui/QuickActions.tsx +msgid "Cancel" +msgstr "Annuler" + +#: src/trainer/ui/category-labels.ts +msgid "Challenge" +msgstr "Défi" + +#: src/trainer/ui/category-labels.ts +msgid "Character" +msgstr "Personnage" + +#: src/trainer/ui/category-labels.ts +msgid "Cheats" +msgstr "Triches" + +#: src/shared/ui/SearchInput.tsx +msgid "Clear search" +msgstr "Effacer la recherche" + +#: src/shared/ui/Drawer.tsx +msgid "Close drawer" +msgstr "Fermer le panneau" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Close library" +msgstr "Fermer la bibliothèque" + +#: src/trainer/ui/QuickActions.tsx +msgid "Close preset modal" +msgstr "Fermer la fenêtre de préréglage" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Close settings" +msgstr "Fermer les paramètres" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Cobalt" +msgstr "Cobalt" + +#: src/trainer/ui/category-labels.ts +msgid "Crafting" +msgstr "Artisanat" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Crimson" +msgstr "Cramoisi" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Custom" +msgstr "Personnalisé" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Cyan" +msgstr "Cyan" + +#. placeholder {0}: preset.name +#: src/trainer/ui/QuickActions.tsx +msgid "Delete preset {0}" +msgstr "Supprimer le préréglage {0}" + +#. placeholder {0}: trainer.totalCheats +#: src/app/app.tsx +msgid "END · {0} MODS" +msgstr "FIN · {0} MODS" + +#: src/trainer/ui/category-labels.ts +msgid "Enemies" +msgstr "Ennemis" + +#: src/library/ui/LibraryDrawer.tsx +#: src/trainer/ui/TrainerHeader.tsx +msgid "Favorite game" +msgstr "Mettre en favori" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Favorites" +msgstr "Favoris" + +#: src/trainer/ui/category-labels.ts +msgid "Game" +msgstr "Jeu" + +#: src/app/ui/SettingsDrawer.tsx +msgid "GO" +msgstr "GO" + +#: src/app/ui/TopBar.tsx +msgid "Idle · no game" +msgstr "Inactif · aucun jeu" + +#: src/trainer/ui/category-labels.ts +msgid "Inventory" +msgstr "Inventaire" + +#: src/trainer/ui/category-labels.ts +msgid "Items" +msgstr "Objets" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Language" +msgstr "Langue" + +#: src/app/ui/FloatingDock.tsx +#: src/library/ui/LibraryDrawer.tsx +msgid "Library" +msgstr "Bibliothèque" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Lime" +msgstr "Citron vert" + +#: src/app/ui/StatusPill.tsx +msgid "LINKING" +msgstr "CONNEXION" + +#: src/app/ui/StatusPill.tsx +msgid "LIVE" +msgstr "EN DIRECT" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Magenta" +msgstr "Magenta" + +#: src/trainer/ui/QuickActions.tsx +msgid "Name" +msgstr "Nom" + +#: src/trainer/ui/QuickActions.tsx +msgid "New preset" +msgstr "Nouveau préréglage" + +#: src/app/ui/SettingsDrawer.tsx +msgid "No active game session." +msgstr "Aucune session de jeu active." + +#: src/app/ui/SessionPlaceholder.tsx +msgid "No game is running yet. Open the library and launch one to start tweaking." +msgstr "Aucun jeu n'est lancé. Ouvrez la bibliothèque et lancez-en un pour commencer." + +#: src/library/ui/LibraryDrawer.tsx +msgid "No games match \"{query}\"" +msgstr "Aucun jeu pour « {query} »" + +#. placeholder {0}: trainer.query +#: src/app/app.tsx +msgid "No mods match \"{0}\"" +msgstr "Aucun mod pour « {0} »" + +#: src/trainer/controls/SelectionControl.tsx +msgid "No options" +msgstr "Aucune option" + +#: src/app/ui/FloatingDock.tsx +msgid "No session" +msgstr "Aucune session" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Now Playing" +msgstr "En cours" + +#: src/app/ui/StatusPill.tsx +msgid "OFFLINE" +msgstr "HORS LIGNE" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Open Settings" +msgstr "Ouvrir les paramètres" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Open Settings to point Wand at your trainer bridge over WebSocket." +msgstr "Ouvrez les paramètres pour connecter Wand à votre pont de trainer via WebSocket." + +#: src/trainer/ui/QuickActions.tsx +msgid "Panic Off" +msgstr "Tout désactiver" + +#: src/trainer/ui/category-labels.ts +msgid "Physics" +msgstr "Physique" + +#: src/trainer/ui/category-labels.ts +msgid "Pinned" +msgstr "Épinglés" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Play" +msgstr "Jouer" + +#: src/trainer/ui/category-labels.ts +msgid "Player" +msgstr "Joueur" + +#: src/trainer/ui/QuickActions.tsx +msgid "Preset name" +msgstr "Nom du préréglage" + +#: src/library/ui/LibraryDrawer.tsx +#: src/trainer/ui/TrainerHeader.tsx +msgid "Remove favorite" +msgstr "Retirer des favoris" + +#: src/trainer/ui/category-labels.ts +msgid "Resources" +msgstr "Ressources" + +#: src/trainer/ui/QuickActions.tsx +msgid "Save" +msgstr "Enregistrer" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Search games" +msgstr "Rechercher des jeux" + +#: src/app/app.tsx +msgid "Search mods" +msgstr "Rechercher des mods" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Select a game" +msgstr "Choisir un jeu" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Session" +msgstr "Session" + +#: src/app/ui/FloatingDock.tsx +#: src/app/ui/SettingsDrawer.tsx +#: src/app/ui/TopBar.tsx +msgid "Settings" +msgstr "Paramètres" + +#: src/trainer/ui/category-labels.ts +msgid "Stats" +msgstr "Stats" + +#: src/app/ui/SettingsDrawer.tsx +msgid "STOP" +msgstr "STOP" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Stop playing" +msgstr "Arrêter" + +#: src/trainer/ui/category-labels.ts +msgid "Teleport" +msgstr "Téléportation" + +#: src/trainer/ui/TrainerHeader.tsx +msgid "Trainer Active" +msgstr "Trainer actif" + +#: src/trainer/ui/category-labels.ts +msgid "Vehicles" +msgstr "Véhicules" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Violet" +msgstr "Violet" + +#. placeholder {0}: WEB_CONTRACT.defaultRemotePort +#: src/app/ui/SettingsDrawer.tsx +msgid "wand remote · port {0}" +msgstr "wand remote · port {0}" + +#: src/trainer/ui/category-labels.ts +msgid "Weapons" +msgstr "Armes" + +#: src/trainer/ui/category-labels.ts +msgid "World" +msgstr "Monde" diff --git a/web-panel/src/locales/ru-RU/messages.po b/web-panel/src/locales/ru-RU/messages.po new file mode 100644 index 0000000..3111bdc --- /dev/null +++ b/web-panel/src/locales/ru-RU/messages.po @@ -0,0 +1,345 @@ +msgid "" +msgstr "" +"POT-Creation-Date: 2026-06-15 00:17+0300\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: @lingui/cli\n" +"Language: ru-RU\n" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Plural-Forms: \n" + +#. placeholder {0}: games.length +#: src/library/ui/LibraryDrawer.tsx +msgid "{0, plural, one {# game detected} other {# games detected}}" +msgstr "{0, plural, one {# игра найдена} few {# игры найдено} many {# игр найдено} other {# игр найдено}}" + +#. placeholder {0}: trainer.totalVisibleCheats +#: src/app/app.tsx +msgid "{0} matches" +msgstr "{0} совпадений" + +#: src/trainer/ui/CategorySection.tsx +msgid "{cheatCount} mods" +msgstr "{cheatCount} модов" + +#: src/trainer/ui/CategorySection.tsx +msgid "{cheatCount} mods · {enabledCount}/{toggleCount} on" +msgstr "{cheatCount} модов · {enabledCount}/{toggleCount} вкл" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Accent Color" +msgstr "Акцентный цвет" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Active Session" +msgstr "Активная сессия" + +#: src/trainer/ui/QuickActions.tsx +msgid "Add" +msgstr "Добавить" + +#: src/trainer/ui/QuickActions.tsx +msgid "Add Preset" +msgstr "Добавить пресет" + +#: src/library/ui/LibraryDrawer.tsx +msgid "All Games" +msgstr "Все игры" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Amber" +msgstr "Янтарный" + +#: src/trainer/controls/ActionButton.tsx +msgid "Apply" +msgstr "Применить" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Bridge" +msgstr "Мост" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Bridge offline" +msgstr "Мост не в сети" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Browse library" +msgstr "Открыть библиотеку" + +#: src/trainer/ui/QuickActions.tsx +msgid "Cancel" +msgstr "Отмена" + +#: src/trainer/ui/category-labels.ts +msgid "Challenge" +msgstr "Испытание" + +#: src/trainer/ui/category-labels.ts +msgid "Character" +msgstr "Персонаж" + +#: src/trainer/ui/category-labels.ts +msgid "Cheats" +msgstr "Читы" + +#: src/shared/ui/SearchInput.tsx +msgid "Clear search" +msgstr "Очистить поиск" + +#: src/shared/ui/Drawer.tsx +msgid "Close drawer" +msgstr "Закрыть панель" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Close library" +msgstr "Закрыть библиотеку" + +#: src/trainer/ui/QuickActions.tsx +msgid "Close preset modal" +msgstr "Закрыть окно пресета" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Close settings" +msgstr "Закрыть настройки" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Cobalt" +msgstr "Кобальт" + +#: src/trainer/ui/category-labels.ts +msgid "Crafting" +msgstr "Крафт" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Crimson" +msgstr "Багровый" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Custom" +msgstr "Свой" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Cyan" +msgstr "Циан" + +#. placeholder {0}: preset.name +#: src/trainer/ui/QuickActions.tsx +msgid "Delete preset {0}" +msgstr "Удалить пресет {0}" + +#. placeholder {0}: trainer.totalCheats +#: src/app/app.tsx +msgid "END · {0} MODS" +msgstr "КОНЕЦ · {0} МОДОВ" + +#: src/trainer/ui/category-labels.ts +msgid "Enemies" +msgstr "Враги" + +#: src/library/ui/LibraryDrawer.tsx +#: src/trainer/ui/TrainerHeader.tsx +msgid "Favorite game" +msgstr "В избранное" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Favorites" +msgstr "Избранное" + +#: src/trainer/ui/category-labels.ts +msgid "Game" +msgstr "Игра" + +#: src/app/ui/SettingsDrawer.tsx +msgid "GO" +msgstr "ПУСК" + +#: src/app/ui/TopBar.tsx +msgid "Idle · no game" +msgstr "Простой · нет игры" + +#: src/trainer/ui/category-labels.ts +msgid "Inventory" +msgstr "Инвентарь" + +#: src/trainer/ui/category-labels.ts +msgid "Items" +msgstr "Предметы" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Language" +msgstr "Язык" + +#: src/app/ui/FloatingDock.tsx +#: src/library/ui/LibraryDrawer.tsx +msgid "Library" +msgstr "Библиотека" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Lime" +msgstr "Лайм" + +#: src/app/ui/StatusPill.tsx +msgid "LINKING" +msgstr "ПОДКЛЮЧЕНИЕ" + +#: src/app/ui/StatusPill.tsx +msgid "LIVE" +msgstr "В СЕТИ" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Magenta" +msgstr "Пурпурный" + +#: src/trainer/ui/QuickActions.tsx +msgid "Name" +msgstr "Название" + +#: src/trainer/ui/QuickActions.tsx +msgid "New preset" +msgstr "Новый пресет" + +#: src/app/ui/SettingsDrawer.tsx +msgid "No active game session." +msgstr "Нет активной игровой сессии." + +#: src/app/ui/SessionPlaceholder.tsx +msgid "No game is running yet. Open the library and launch one to start tweaking." +msgstr "Игра ещё не запущена. Откройте библиотеку и запустите игру, чтобы начать настройку." + +#: src/library/ui/LibraryDrawer.tsx +msgid "No games match \"{query}\"" +msgstr "Нет игр по запросу «{query}»" + +#. placeholder {0}: trainer.query +#: src/app/app.tsx +msgid "No mods match \"{0}\"" +msgstr "Нет модов по запросу «{0}»" + +#: src/trainer/controls/SelectionControl.tsx +msgid "No options" +msgstr "Нет вариантов" + +#: src/app/ui/FloatingDock.tsx +msgid "No session" +msgstr "Нет сессии" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Now Playing" +msgstr "Сейчас в игре" + +#: src/app/ui/StatusPill.tsx +msgid "OFFLINE" +msgstr "НЕ В СЕТИ" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Open Settings" +msgstr "Открыть настройки" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Open Settings to point Wand at your trainer bridge over WebSocket." +msgstr "Откройте настройки, чтобы указать Wand адрес моста трейнера по WebSocket." + +#: src/trainer/ui/QuickActions.tsx +msgid "Panic Off" +msgstr "Выключить всё" + +#: src/trainer/ui/category-labels.ts +msgid "Physics" +msgstr "Физика" + +#: src/trainer/ui/category-labels.ts +msgid "Pinned" +msgstr "Закреплённые" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Play" +msgstr "Играть" + +#: src/trainer/ui/category-labels.ts +msgid "Player" +msgstr "Игрок" + +#: src/trainer/ui/QuickActions.tsx +msgid "Preset name" +msgstr "Название пресета" + +#: src/library/ui/LibraryDrawer.tsx +#: src/trainer/ui/TrainerHeader.tsx +msgid "Remove favorite" +msgstr "Убрать из избранного" + +#: src/trainer/ui/category-labels.ts +msgid "Resources" +msgstr "Ресурсы" + +#: src/trainer/ui/QuickActions.tsx +msgid "Save" +msgstr "Сохранить" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Search games" +msgstr "Поиск игр" + +#: src/app/app.tsx +msgid "Search mods" +msgstr "Поиск модов" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Select a game" +msgstr "Выберите игру" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Session" +msgstr "Сессия" + +#: src/app/ui/FloatingDock.tsx +#: src/app/ui/SettingsDrawer.tsx +#: src/app/ui/TopBar.tsx +msgid "Settings" +msgstr "Настройки" + +#: src/trainer/ui/category-labels.ts +msgid "Stats" +msgstr "Статы" + +#: src/app/ui/SettingsDrawer.tsx +msgid "STOP" +msgstr "СТОП" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Stop playing" +msgstr "Остановить" + +#: src/trainer/ui/category-labels.ts +msgid "Teleport" +msgstr "Телепорт" + +#: src/trainer/ui/TrainerHeader.tsx +msgid "Trainer Active" +msgstr "Трейнер активен" + +#: src/trainer/ui/category-labels.ts +msgid "Vehicles" +msgstr "Транспорт" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Violet" +msgstr "Фиолетовый" + +#. placeholder {0}: WEB_CONTRACT.defaultRemotePort +#: src/app/ui/SettingsDrawer.tsx +msgid "wand remote · port {0}" +msgstr "wand remote · порт {0}" + +#: src/trainer/ui/category-labels.ts +msgid "Weapons" +msgstr "Оружие" + +#: src/trainer/ui/category-labels.ts +msgid "World" +msgstr "Мир" diff --git a/web-panel/src/locales/zh-CN/messages.po b/web-panel/src/locales/zh-CN/messages.po new file mode 100644 index 0000000..9e606a9 --- /dev/null +++ b/web-panel/src/locales/zh-CN/messages.po @@ -0,0 +1,345 @@ +msgid "" +msgstr "" +"POT-Creation-Date: 2026-06-15 00:17+0300\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: @lingui/cli\n" +"Language: zh-CN\n" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Plural-Forms: \n" + +#. placeholder {0}: games.length +#: src/library/ui/LibraryDrawer.tsx +msgid "{0, plural, one {# game detected} other {# games detected}}" +msgstr "{0, plural, other {检测到 # 个游戏}}" + +#. placeholder {0}: trainer.totalVisibleCheats +#: src/app/app.tsx +msgid "{0} matches" +msgstr "{0} 个匹配" + +#: src/trainer/ui/CategorySection.tsx +msgid "{cheatCount} mods" +msgstr "{cheatCount} 个模组" + +#: src/trainer/ui/CategorySection.tsx +msgid "{cheatCount} mods · {enabledCount}/{toggleCount} on" +msgstr "{cheatCount} 个模组 · {enabledCount}/{toggleCount} 已开" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Accent Color" +msgstr "强调色" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Active Session" +msgstr "当前会话" + +#: src/trainer/ui/QuickActions.tsx +msgid "Add" +msgstr "添加" + +#: src/trainer/ui/QuickActions.tsx +msgid "Add Preset" +msgstr "添加预设" + +#: src/library/ui/LibraryDrawer.tsx +msgid "All Games" +msgstr "所有游戏" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Amber" +msgstr "琥珀" + +#: src/trainer/controls/ActionButton.tsx +msgid "Apply" +msgstr "应用" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Bridge" +msgstr "桥接" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Bridge offline" +msgstr "桥接已离线" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Browse library" +msgstr "浏览游戏库" + +#: src/trainer/ui/QuickActions.tsx +msgid "Cancel" +msgstr "取消" + +#: src/trainer/ui/category-labels.ts +msgid "Challenge" +msgstr "挑战" + +#: src/trainer/ui/category-labels.ts +msgid "Character" +msgstr "角色" + +#: src/trainer/ui/category-labels.ts +msgid "Cheats" +msgstr "作弊" + +#: src/shared/ui/SearchInput.tsx +msgid "Clear search" +msgstr "清除搜索" + +#: src/shared/ui/Drawer.tsx +msgid "Close drawer" +msgstr "关闭抽屉" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Close library" +msgstr "关闭游戏库" + +#: src/trainer/ui/QuickActions.tsx +msgid "Close preset modal" +msgstr "关闭预设窗口" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Close settings" +msgstr "关闭设置" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Cobalt" +msgstr "钴蓝" + +#: src/trainer/ui/category-labels.ts +msgid "Crafting" +msgstr "制作" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Crimson" +msgstr "深红" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Custom" +msgstr "自定义" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Cyan" +msgstr "青色" + +#. placeholder {0}: preset.name +#: src/trainer/ui/QuickActions.tsx +msgid "Delete preset {0}" +msgstr "删除预设 {0}" + +#. placeholder {0}: trainer.totalCheats +#: src/app/app.tsx +msgid "END · {0} MODS" +msgstr "结束 · {0} 个模组" + +#: src/trainer/ui/category-labels.ts +msgid "Enemies" +msgstr "敌人" + +#: src/library/ui/LibraryDrawer.tsx +#: src/trainer/ui/TrainerHeader.tsx +msgid "Favorite game" +msgstr "收藏游戏" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Favorites" +msgstr "收藏" + +#: src/trainer/ui/category-labels.ts +msgid "Game" +msgstr "游戏" + +#: src/app/ui/SettingsDrawer.tsx +msgid "GO" +msgstr "连接" + +#: src/app/ui/TopBar.tsx +msgid "Idle · no game" +msgstr "空闲 · 无游戏" + +#: src/trainer/ui/category-labels.ts +msgid "Inventory" +msgstr "物品栏" + +#: src/trainer/ui/category-labels.ts +msgid "Items" +msgstr "物品" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Language" +msgstr "语言" + +#: src/app/ui/FloatingDock.tsx +#: src/library/ui/LibraryDrawer.tsx +msgid "Library" +msgstr "游戏库" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Lime" +msgstr "青柠" + +#: src/app/ui/StatusPill.tsx +msgid "LINKING" +msgstr "连接中" + +#: src/app/ui/StatusPill.tsx +msgid "LIVE" +msgstr "在线" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Magenta" +msgstr "品红" + +#: src/trainer/ui/QuickActions.tsx +msgid "Name" +msgstr "名称" + +#: src/trainer/ui/QuickActions.tsx +msgid "New preset" +msgstr "新预设" + +#: src/app/ui/SettingsDrawer.tsx +msgid "No active game session." +msgstr "没有活动的游戏会话。" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "No game is running yet. Open the library and launch one to start tweaking." +msgstr "尚未运行游戏。打开游戏库并启动一个即可开始调整。" + +#: src/library/ui/LibraryDrawer.tsx +msgid "No games match \"{query}\"" +msgstr "没有匹配「{query}」的游戏" + +#. placeholder {0}: trainer.query +#: src/app/app.tsx +msgid "No mods match \"{0}\"" +msgstr "没有匹配「{0}」的模组" + +#: src/trainer/controls/SelectionControl.tsx +msgid "No options" +msgstr "无选项" + +#: src/app/ui/FloatingDock.tsx +msgid "No session" +msgstr "无会话" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Now Playing" +msgstr "正在游玩" + +#: src/app/ui/StatusPill.tsx +msgid "OFFLINE" +msgstr "离线" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Open Settings" +msgstr "打开设置" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Open Settings to point Wand at your trainer bridge over WebSocket." +msgstr "打开设置,通过 WebSocket 将 Wand 指向你的训练器桥接。" + +#: src/trainer/ui/QuickActions.tsx +msgid "Panic Off" +msgstr "全部关闭" + +#: src/trainer/ui/category-labels.ts +msgid "Physics" +msgstr "物理" + +#: src/trainer/ui/category-labels.ts +msgid "Pinned" +msgstr "已固定" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Play" +msgstr "开始游戏" + +#: src/trainer/ui/category-labels.ts +msgid "Player" +msgstr "玩家" + +#: src/trainer/ui/QuickActions.tsx +msgid "Preset name" +msgstr "预设名称" + +#: src/library/ui/LibraryDrawer.tsx +#: src/trainer/ui/TrainerHeader.tsx +msgid "Remove favorite" +msgstr "取消收藏" + +#: src/trainer/ui/category-labels.ts +msgid "Resources" +msgstr "资源" + +#: src/trainer/ui/QuickActions.tsx +msgid "Save" +msgstr "保存" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Search games" +msgstr "搜索游戏" + +#: src/app/app.tsx +msgid "Search mods" +msgstr "搜索模组" + +#: src/app/ui/SessionPlaceholder.tsx +msgid "Select a game" +msgstr "选择游戏" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Session" +msgstr "会话" + +#: src/app/ui/FloatingDock.tsx +#: src/app/ui/SettingsDrawer.tsx +#: src/app/ui/TopBar.tsx +msgid "Settings" +msgstr "设置" + +#: src/trainer/ui/category-labels.ts +msgid "Stats" +msgstr "属性" + +#: src/app/ui/SettingsDrawer.tsx +msgid "STOP" +msgstr "停止" + +#: src/library/ui/LibraryDrawer.tsx +msgid "Stop playing" +msgstr "停止游戏" + +#: src/trainer/ui/category-labels.ts +msgid "Teleport" +msgstr "传送" + +#: src/trainer/ui/TrainerHeader.tsx +msgid "Trainer Active" +msgstr "训练器已激活" + +#: src/trainer/ui/category-labels.ts +msgid "Vehicles" +msgstr "载具" + +#: src/app/ui/SettingsDrawer.tsx +msgid "Violet" +msgstr "紫色" + +#. placeholder {0}: WEB_CONTRACT.defaultRemotePort +#: src/app/ui/SettingsDrawer.tsx +msgid "wand remote · port {0}" +msgstr "wand remote · 端口 {0}" + +#: src/trainer/ui/category-labels.ts +msgid "Weapons" +msgstr "武器" + +#: src/trainer/ui/category-labels.ts +msgid "World" +msgstr "世界"