From 38b5b86be1bcc8a778157fc1e2471f0e94fea68a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Wed, 30 Sep 2026 21:32:15 +0500 Subject: [PATCH] Translations: settings schema overlays (ru/de/fr/es), diagnostics, update steps, companion sizes, friends notes; dev mock for settings pages; docs/TRANSLATIONS.md Co-Authored-By: Claude Sonnet 5.5 --- docs/ARCHITECTURE.md | 8 +- docs/TRANSLATIONS.md | 36 +++ src/dev/mock.ts | 12 +- src/i18n/index.tsx | 30 ++ src/i18n/locales/de.ts | 64 ++++ src/i18n/locales/en.ts | 64 ++++ src/i18n/locales/es.ts | 64 ++++ src/i18n/locales/fr.ts | 64 ++++ src/i18n/locales/ru.ts | 64 ++++ src/i18n/schema/de.json | 513 ++++++++++++++++++++++++++++++++ src/i18n/schema/es.json | 513 ++++++++++++++++++++++++++++++++ src/i18n/schema/fr.json | 513 ++++++++++++++++++++++++++++++++ src/i18n/schema/ru.json | 513 ++++++++++++++++++++++++++++++++ src/screens/CompanionsCard.tsx | 13 +- src/screens/DiagnosticsCard.tsx | 39 ++- src/screens/FriendsPage.tsx | 2 +- src/screens/ImportServer.tsx | 4 +- src/screens/Placeholder.tsx | 5 +- src/screens/SettingsHome.tsx | 4 +- src/screens/SettingsPage.tsx | 42 +-- tools/check-i18n.mjs | 17 ++ tsconfig.json | 1 + 22 files changed, 2552 insertions(+), 33 deletions(-) create mode 100644 docs/TRANSLATIONS.md create mode 100644 src/i18n/schema/de.json create mode 100644 src/i18n/schema/es.json create mode 100644 src/i18n/schema/fr.json create mode 100644 src/i18n/schema/ru.json diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index caad090..2068d18 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -484,9 +484,11 @@ The reference install classifies as **Healthy (customised)**: repack shape, bina translations are reviewed by native speakers before release, with an English fallback for missing keys and a CI check that every locale has every key. Do this before the first public release so strings are not retro-fitted. - **Status (2026-09-30):** catalogue + picker + all screens translated (en/ru/de/fr/es drafts, `tools/check-i18n.mjs` checks - keys/placeholders). Still English: settings-schema titles/descriptions/presets, companion size names, diagnostics check - texts and update step names coming from the backend (need `schemas/i18n/.json` overlays and code-keyed backend strings). + **Status (2026-09-30, updated):** catalogue + picker + every screen translated (en/ru/de/fr/es drafts); settings-schema titles, + descriptions, categories, presets, options and units are translated through overlays in `src/i18n/schema/`; diagnostics + checks, update steps, companion sizes and friends notes are recognised and translated in the UI. `tools/check-i18n.mjs` + verifies keys, placeholders and overlay coverage. Still English: free-form backend technical messages. Native-speaker + review is still needed (see `docs/TRANSLATIONS.md`). * **Language choice on the very first screen** (requested 2026-09-30): the welcome screen must offer the language picker right away (before any other text is read), preselected from the OS language; the choice is persisted and shared with diff --git a/docs/TRANSLATIONS.md b/docs/TRANSLATIONS.md new file mode 100644 index 0000000..06135b6 --- /dev/null +++ b/docs/TRANSLATIONS.md @@ -0,0 +1,36 @@ +# Translations + +The Manager interface exists in English (source), Russian, German, French and Spanish. Everything except English is a +**draft written by an AI assistant and needs review by a native speaker** before it is treated as final. + +## Where the texts are + +| What | File | Notes | +|---|---|---| +| Interface texts | `src/i18n/locales/.ts` | flat `"key": "text"` lists; `en.ts` is the source of truth, other languages fall back to it | +| Setting titles, descriptions, categories, presets, units, option labels | `src/i18n/schema/.json` | generated once from `schemas/*.json`; edit the JSON directly | +| Backend error messages | keys `err..title` / `err..message` in the locale files | codes come from `crates/coa-core/src/error.rs` | + +`{name}` placeholders must stay exactly as they are. Plural forms use the suffixes `_one`, `_few`, `_many`, `_other` +(the browser picks the right one for the language). + +## Checking your work + +``` +node tools/check-i18n.mjs # unknown keys, changed placeholders, coverage, schema overlays complete +npx tsc --noEmit # types +npx vite # UI with mock data in a browser; pick the language on the welcome screen +``` + +## Adding a language + +1. Copy `src/i18n/locales/en.ts` to `.ts` (keep the keys), translate, and register it in `src/i18n/index.tsx` + (`Locale`, `LOCALES`, `DICTS`). +2. Copy `src/i18n/schema/ru.json` to `.json`, translate the values, and register it in `SCHEMA`. +3. Run the check above. + +## Known gaps + +* Free-form technical messages produced deep inside the backend (`Error::Invalid("...")`) stay in English; they are + shown as "technical details". +* Texts inside the game itself (client, server data) are not part of the Manager. diff --git a/src/dev/mock.ts b/src/dev/mock.ts index 338cb9a..4e26717 100644 --- a/src/dev/mock.ts +++ b/src/dev/mock.ts @@ -1,4 +1,8 @@ // Dev-only: lets the UI run in a plain browser for visual review. Never bundled in production builds. +import botsSchema from "../../schemas/bots.json"; +import serverSchema from "../../schemas/server.json"; +import botsPresets from "../../schemas/presets/bots.json"; +import serverPresets from "../../schemas/presets/server.json"; export {}; (() => { @@ -14,7 +18,7 @@ export {}; const svc=(n: string,p: number,st: string)=>({name:n,state:st,pid:st==="running"?100:null,port:p,port_ready:st==="running",conflict:null,uptime_secs:st==="running"?4206:null}); (window as any).__TAURI_INTERNALS__ = { transformCallback: (cb: unknown)=>cb, unregisterCallback(){}, convertFileSrc:(x: unknown)=>x, - invoke: async (cmd: string)=>{ + invoke: async (cmd: string, args?: any)=>{ if(cmd==="list_servers") return added?[{id:"1",name:"CoA-Repack",path:report.path}]:[]; if(cmd==="scan_server") return report; if(cmd==="add_server"){added=true;return {id:"1",name:"CoA-Repack",path:report.path};} @@ -22,6 +26,12 @@ export {}; if(cmd==="start_server"){await new Promise((r: any)=>setTimeout(r,1500));running=true;return {ok:true,exit_code:0,code:null,human:null,output:""};} if(cmd==="stop_server"){await new Promise((r: any)=>setTimeout(r,1500));running=false;return {ok:true,exit_code:0,code:null,human:null,output:""};} if(cmd.startsWith("plugin:dialog")) return "C:\games\CoA-Repack"; + if(cmd==="get_settings"){const sc=args?.scope==="server"?serverSchema:botsSchema;return {scope:args?.scope,categories:sc.categories,settings:(sc.settings as any[]).map(x=>({...x,options:x.options??[],value:x.default,is_default:true,present:true,problem:null,drift:false})),unknown_keys:3,drift_keys:[],files:[]};} + if(cmd==="list_presets"){const pr=args?.scope==="server"?serverPresets:botsPresets;return (pr.presets as any[]).map(p=>({id:p.id,title:p.title,description:p.description}));} + if(cmd==="preview_preset"){const a=args;const sc=a.scope==="server"?serverSchema:botsSchema;const pr=(a.scope==="server"?serverPresets:botsPresets).presets as any[];const p=pr.find(x=>x.id===a.preset)??{id:a.preset??"defaults",title:"Recommended defaults",description:"Every setting returns to its default value."};const st=(sc.settings as any[]).filter(x=>x.type==="int"||x.type==="float"||x.type==="enum").slice(0,3);return {id:p.id,title:p.title,description:p.description,changes:st.map(x=>({key:x.key,title:x.title,from:x.default,to:x.type==="enum"?(x.options?.[1]?.value??x.default):(Number(x.default)||1)*2,dangerous:false}))};} + if(cmd==="companion_sizes") return {hardware:{cores:16,ram_gb:31,free_ram_gb:12},sizes:[{id:"small",title:"Small",bots:50,warning:null},{id:"medium",title:"Medium",bots:250,warning:null},{id:"large",title:"Large",bots:500,warning:"500 companions may need more CPU and memory than this computer has (8 cores, 16 GB)."}]}; + if(cmd==="get_population") return null; + if(cmd==="run_diagnostics") return {problems:2,checks:[{id:"files",title:"Server files",level:"ok",detail:"All expected server parts were found."},{id:"world",title:"World server",level:"warn",detail:"Not running."},{id:"disk",title:"Free disk space",level:"warn",detail:"Only 3 GB free; backups and updates need room."},{id:"exposure",title:"Private services",level:"ok",detail:"Database and server console are not reachable from the network."}]}; if(cmd==="plugin:event|listen") return 1; if(cmd==="plugin:event|unlisten") return null; throw new Error("unmocked "+cmd); diff --git a/src/i18n/index.tsx b/src/i18n/index.tsx index 73e0f5e..f83ac56 100644 --- a/src/i18n/index.tsx +++ b/src/i18n/index.tsx @@ -4,6 +4,10 @@ import ru from "./locales/ru"; import de from "./locales/de"; import fr from "./locales/fr"; import es from "./locales/es"; +import ruSchema from "./schema/ru.json"; +import deSchema from "./schema/de.json"; +import frSchema from "./schema/fr.json"; +import esSchema from "./schema/es.json"; export type Locale = "en" | "ru" | "de" | "fr" | "es"; export type Key = keyof typeof en; @@ -83,6 +87,29 @@ export function I18nProvider({ children }: { children: ReactNode }) { export const useI18n = () => useContext(I18n); +/** Translated text of the settings schemas (titles, descriptions, categories, presets, units). English comes from the backend. */ +interface SchemaOverlay { + categories: Record; + units: Record; + settings: Record; + options: Record; + presets: Record; +} +const SCHEMA: Partial> = { ru: ruSchema, de: deSchema, fr: frSchema, es: esSchema }; + +export function useSchemaText() { + const { locale } = useContext(I18n); + const o = SCHEMA[locale]; + return { + title: (s: { key: string; title: string }) => o?.settings[s.key]?.t ?? s.title, + description: (s: { key: string; description: string }) => o?.settings[s.key]?.d ?? s.description, + category: (scope: string, c: { id: string; title: string }) => o?.categories[`${scope}.${c.id}`] ?? c.title, + option: (key: string, opt: { value: unknown; label: string }) => o?.options[`${key}.${String(opt.value)}`] ?? opt.label, + unit: (u: string) => o?.units[u] ?? u, + preset: (p: { id: string; title: string; description: string }) => ({ title: o?.presets[p.id]?.t ?? p.title, description: o?.presets[p.id]?.d ?? p.description }), + }; +} + /** Translated title/message for a backend error; falls back to the backend's English text for unknown codes. */ export function useHuman() { const { t } = useContext(I18n); @@ -93,3 +120,6 @@ export function useHuman() { }; } export const useT = () => useContext(I18n).t; + +/** True when `key` exists in the catalogue (backend-supplied texts are translated only when a key is defined for them). */ +export const hasKey = (key: string): key is Key => key in en; diff --git a/src/i18n/locales/de.ts b/src/i18n/locales/de.ts index f492b08..3bd82f3 100644 --- a/src/i18n/locales/de.ts +++ b/src/i18n/locales/de.ts @@ -433,6 +433,70 @@ const de: Partial> = { // Friends line "fr.copyLine": "Zeile kopieren", + + // Diagnostics checks + "dg.title.files": "Serverdateien", + "dg.title.missing_parts": "Fehlende Teile", + "dg.title.mysql": "Datenbank", + "dg.title.auth": "Anmeldeserver", + "dg.title.world": "Weltserver", + "dg.title.configs": "Konfiguration", + "dg.title.config_values": "Einstellungswerte", + "dg.title.disk": "Freier Speicherplatz", + "dg.title.permissions": "Berechtigungen", + "dg.title.client": "Spielclient", + "dg.title.exposure": "Private Dienste", + "dg.files.ok": "Alle erwarteten Serverteile wurden gefunden.", + "dg.files.partial": "Einige Serverteile fehlen.", + "dg.files.custom": "Dies ist ein angepasster Server-Build; einige Funktionen sind eingeschränkt.", + "dg.files.bad": "Dieser Ordner sieht nicht wie ein CoA-Server aus.", + "dg.svc.running": "Läuft", + "dg.svc.port": "Port {port} wird von einem anderen Programm verwendet (Prozess {pid}).", + "dg.svc.starting": "Startet, antwortet noch nicht.", + "dg.svc.stopped": "Läuft nicht.", + "dg.configs.ok": "Konfigurationsdateien können gelesen werden.", + "dg.configs.bad": "Nicht lesbar: {files}", + "dg.values.bad": "Unbrauchbare Werte bei: {keys}", + "dg.disk.ok": "{gb} GB frei", + "dg.disk.low": "Nur {gb} GB frei; Sicherungen und Updates brauchen Platz.", + "dg.perm.ok": "Der Serverordner ist beschreibbar.", + "dg.perm.bad": "Der Manager kann nicht in den Serverordner schreiben (wähle einen anderen Ort oder starte einmal als Administrator).", + "dg.client.missing": "Der gespeicherte Spielordner wurde nicht gefunden; wähle ihn in den Einstellungen erneut.", + "dg.exposure.ok": "Datenbank und Serverkonsole sind aus dem Netzwerk nicht erreichbar.", + "dg.exposure.bad": "Aus dem Netzwerk erreichbar: {what}.", + + // Update steps + "ustep.Starting": "Start", + "ustep.Checking the update": "Update wird geprüft", + "ustep.Downloading the update": "Update wird heruntergeladen", + "ustep.Verifying the update": "Update wird verifiziert", + "ustep.Making sure the server is stopped": "Es wird sichergestellt, dass der Server gestoppt ist", + "ustep.Saving a recovery point": "Wiederherstellungspunkt wird gespeichert", + "ustep.Applying the update": "Update wird angewendet", + "ustep.Updating the database": "Datenbank wird aktualisiert", + "ustep.Starting the updated server": "Aktualisierter Server wird gestartet", + "ustep.Finishing": "Abschluss", + "ustep.Undoing the update": "Update wird rückgängig gemacht", + "ustep.Done": "Fertig", + + // Companion sizes + "comp.size.small": "Klein", + "comp.size.medium": "Mittel", + "comp.size.large": "Groß", + "comp.warnHardware": "{n} Begleiter brauchen möglicherweise mehr CPU und Speicher, als dieser Computer hat ({cores} Kerne, {ram} GB).", + "comp.warnMemory": "Gib zuerst etwas Speicher frei; andere Programme belegen den größten Teil.", + + // Friends notes + "fr.note.forwarded": "Dein Router wurde gebeten, die Spielports weiterzuleiten.", + "fr.note.manual": "Dein Router unterstützt keine automatische Einrichtung; leite die beiden Spielports manuell weiter oder nutze das private Netzwerk.", + + // Import labels and placeholder + "scan.label.worldserver": "Weltserver", + "scan.label.authserver": "Anmeldeserver", + "scan.label.database_content": "Datenbanken für Anmeldung, Charaktere und Welt", + "scan.label.companions": "CoA-Begleiter (Bots)", + "scan.label.client": "Spielclient", + "placeholder.soon": "Dieser Bereich entsteht in einer späteren Version.", }; export default de; diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index 3d221d9..3ac7bd5 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -433,6 +433,70 @@ const en = { // Friends line "fr.copyLine": "Copy line", + + // Diagnostics checks + "dg.title.files": "Server files", + "dg.title.missing_parts": "Missing parts", + "dg.title.mysql": "Database", + "dg.title.auth": "Login server", + "dg.title.world": "World server", + "dg.title.configs": "Configuration", + "dg.title.config_values": "Setting values", + "dg.title.disk": "Free disk space", + "dg.title.permissions": "Permissions", + "dg.title.client": "Game client", + "dg.title.exposure": "Private services", + "dg.files.ok": "All expected server parts were found.", + "dg.files.partial": "Some server parts are missing.", + "dg.files.custom": "This is a custom server build; some features are limited.", + "dg.files.bad": "This folder does not look like a CoA server.", + "dg.svc.running": "Running", + "dg.svc.port": "Port {port} is used by another program (process {pid}).", + "dg.svc.starting": "Starting, not answering yet.", + "dg.svc.stopped": "Not running.", + "dg.configs.ok": "Configuration files can be read.", + "dg.configs.bad": "Cannot read: {files}", + "dg.values.bad": "Unusable values for: {keys}", + "dg.disk.ok": "{gb} GB free", + "dg.disk.low": "Only {gb} GB free; backups and updates need room.", + "dg.perm.ok": "The server folder is writable.", + "dg.perm.bad": "The Manager cannot write to the server folder (try another location or run once as administrator).", + "dg.client.missing": "The saved game folder was not found; choose it again in Settings.", + "dg.exposure.ok": "Database and server console are not reachable from the network.", + "dg.exposure.bad": "Reachable from the network: {what}.", + + // Update steps + "ustep.Starting": "Starting", + "ustep.Checking the update": "Checking the update", + "ustep.Downloading the update": "Downloading the update", + "ustep.Verifying the update": "Verifying the update", + "ustep.Making sure the server is stopped": "Making sure the server is stopped", + "ustep.Saving a recovery point": "Saving a recovery point", + "ustep.Applying the update": "Applying the update", + "ustep.Updating the database": "Updating the database", + "ustep.Starting the updated server": "Starting the updated server", + "ustep.Finishing": "Finishing", + "ustep.Undoing the update": "Undoing the update", + "ustep.Done": "Done", + + // Companion sizes + "comp.size.small": "Small", + "comp.size.medium": "Medium", + "comp.size.large": "Large", + "comp.warnHardware": "{n} companions may need more CPU and memory than this computer has ({cores} cores, {ram} GB).", + "comp.warnMemory": "Free some memory first; other programs are using most of it.", + + // Friends notes + "fr.note.forwarded": "Your router was asked to forward the game ports.", + "fr.note.manual": "Your router does not support automatic setup; forward the two game ports by hand or use the private network.", + + // Import labels and placeholder + "scan.label.worldserver": "World server", + "scan.label.authserver": "Auth server", + "scan.label.database_content": "Auth / Characters / World databases", + "scan.label.companions": "CoA Companions (bots)", + "scan.label.client": "Game client", + "placeholder.soon": "This section is being built in a later release.", } as const; export default en; diff --git a/src/i18n/locales/es.ts b/src/i18n/locales/es.ts index d487e18..d0550d1 100644 --- a/src/i18n/locales/es.ts +++ b/src/i18n/locales/es.ts @@ -433,6 +433,70 @@ const es: Partial> = { // Friends line "fr.copyLine": "Copiar línea", + + // Diagnostics checks + "dg.title.files": "Archivos del servidor", + "dg.title.missing_parts": "Partes que faltan", + "dg.title.mysql": "Base de datos", + "dg.title.auth": "Servidor de acceso", + "dg.title.world": "Servidor del mundo", + "dg.title.configs": "Configuración", + "dg.title.config_values": "Valores de los ajustes", + "dg.title.disk": "Espacio libre en disco", + "dg.title.permissions": "Permisos", + "dg.title.client": "Cliente del juego", + "dg.title.exposure": "Servicios privados", + "dg.files.ok": "Se encontraron todas las partes esperadas del servidor.", + "dg.files.partial": "Faltan algunas partes del servidor.", + "dg.files.custom": "Esta es una versión personalizada del servidor; algunas funciones están limitadas.", + "dg.files.bad": "Esta carpeta no parece un servidor de CoA.", + "dg.svc.running": "En marcha", + "dg.svc.port": "El puerto {port} lo usa otro programa (proceso {pid}).", + "dg.svc.starting": "Iniciándose, aún no responde.", + "dg.svc.stopped": "No está en marcha.", + "dg.configs.ok": "Los archivos de configuración se pueden leer.", + "dg.configs.bad": "No se puede leer: {files}", + "dg.values.bad": "Valores inutilizables en: {keys}", + "dg.disk.ok": "{gb} GB libres", + "dg.disk.low": "Solo {gb} GB libres; las copias y las actualizaciones necesitan espacio.", + "dg.perm.ok": "La carpeta del servidor admite escritura.", + "dg.perm.bad": "El Manager no puede escribir en la carpeta del servidor (prueba otra ubicación o ejecútalo una vez como administrador).", + "dg.client.missing": "No se encontró la carpeta del juego guardada; elígela de nuevo en Ajustes.", + "dg.exposure.ok": "La base de datos y la consola del servidor no son accesibles desde la red.", + "dg.exposure.bad": "Accesible desde la red: {what}.", + + // Update steps + "ustep.Starting": "Iniciando", + "ustep.Checking the update": "Comprobando la actualización", + "ustep.Downloading the update": "Descargando la actualización", + "ustep.Verifying the update": "Verificando la actualización", + "ustep.Making sure the server is stopped": "Comprobando que el servidor está detenido", + "ustep.Saving a recovery point": "Guardando un punto de recuperación", + "ustep.Applying the update": "Aplicando la actualización", + "ustep.Updating the database": "Actualizando la base de datos", + "ustep.Starting the updated server": "Iniciando el servidor actualizado", + "ustep.Finishing": "Finalizando", + "ustep.Undoing the update": "Deshaciendo la actualización", + "ustep.Done": "Hecho", + + // Companion sizes + "comp.size.small": "Pequeño", + "comp.size.medium": "Mediano", + "comp.size.large": "Grande", + "comp.warnHardware": "{n} compañeros pueden necesitar más CPU y memoria de las que tiene este equipo ({cores} núcleos, {ram} GB).", + "comp.warnMemory": "Libera primero algo de memoria; otros programas usan la mayor parte.", + + // Friends notes + "fr.note.forwarded": "Se pidió a tu router que redirigiera los puertos del juego.", + "fr.note.manual": "Tu router no admite la configuración automática; redirige los dos puertos del juego a mano o usa la red privada.", + + // Import labels and placeholder + "scan.label.worldserver": "Servidor del mundo", + "scan.label.authserver": "Servidor de acceso", + "scan.label.database_content": "Bases de datos de acceso, personajes y mundo", + "scan.label.companions": "Compañeros de CoA (bots)", + "scan.label.client": "Cliente del juego", + "placeholder.soon": "Esta sección se está desarrollando para una versión posterior.", }; export default es; diff --git a/src/i18n/locales/fr.ts b/src/i18n/locales/fr.ts index 61aeb1e..ef1b9c3 100644 --- a/src/i18n/locales/fr.ts +++ b/src/i18n/locales/fr.ts @@ -433,6 +433,70 @@ const fr: Partial> = { // Friends line "fr.copyLine": "Copier la ligne", + + // Diagnostics checks + "dg.title.files": "Fichiers du serveur", + "dg.title.missing_parts": "Parties manquantes", + "dg.title.mysql": "Base de données", + "dg.title.auth": "Serveur de connexion", + "dg.title.world": "Serveur de monde", + "dg.title.configs": "Configuration", + "dg.title.config_values": "Valeurs des paramètres", + "dg.title.disk": "Espace disque libre", + "dg.title.permissions": "Autorisations", + "dg.title.client": "Client du jeu", + "dg.title.exposure": "Services privés", + "dg.files.ok": "Toutes les parties attendues du serveur ont été trouvées.", + "dg.files.partial": "Certaines parties du serveur manquent.", + "dg.files.custom": "Il s’agit d’une version personnalisée du serveur ; certaines fonctions sont limitées.", + "dg.files.bad": "Ce dossier ne ressemble pas à un serveur CoA.", + "dg.svc.running": "En cours", + "dg.svc.port": "Le port {port} est utilisé par un autre programme (processus {pid}).", + "dg.svc.starting": "Démarrage, ne répond pas encore.", + "dg.svc.stopped": "Non démarré.", + "dg.configs.ok": "Les fichiers de configuration sont lisibles.", + "dg.configs.bad": "Lecture impossible : {files}", + "dg.values.bad": "Valeurs inutilisables pour : {keys}", + "dg.disk.ok": "{gb} Go libres", + "dg.disk.low": "Seulement {gb} Go libres ; les sauvegardes et mises à jour ont besoin de place.", + "dg.perm.ok": "Le dossier du serveur est accessible en écriture.", + "dg.perm.bad": "Le Manager ne peut pas écrire dans le dossier du serveur (essayez un autre emplacement ou lancez-le une fois en administrateur).", + "dg.client.missing": "Le dossier de jeu enregistré est introuvable ; choisissez-le à nouveau dans les Paramètres.", + "dg.exposure.ok": "La base de données et la console du serveur ne sont pas joignables depuis le réseau.", + "dg.exposure.bad": "Joignable depuis le réseau : {what}.", + + // Update steps + "ustep.Starting": "Démarrage", + "ustep.Checking the update": "Vérification de la mise à jour", + "ustep.Downloading the update": "Téléchargement de la mise à jour", + "ustep.Verifying the update": "Vérification de la mise à jour", + "ustep.Making sure the server is stopped": "Vérification que le serveur est arrêté", + "ustep.Saving a recovery point": "Enregistrement d’un point de restauration", + "ustep.Applying the update": "Application de la mise à jour", + "ustep.Updating the database": "Mise à jour de la base de données", + "ustep.Starting the updated server": "Démarrage du serveur mis à jour", + "ustep.Finishing": "Finalisation", + "ustep.Undoing the update": "Annulation de la mise à jour", + "ustep.Done": "Terminé", + + // Companion sizes + "comp.size.small": "Petit", + "comp.size.medium": "Moyen", + "comp.size.large": "Grand", + "comp.warnHardware": "{n} compagnons peuvent demander plus de processeur et de mémoire que cet ordinateur n’en a ({cores} cœurs, {ram} Go).", + "comp.warnMemory": "Libérez d’abord de la mémoire ; d’autres programmes en utilisent la plus grande partie.", + + // Friends notes + "fr.note.forwarded": "Votre routeur a été invité à rediriger les ports du jeu.", + "fr.note.manual": "Votre routeur ne prend pas en charge la configuration automatique ; redirigez les deux ports du jeu à la main ou utilisez le réseau privé.", + + // Import labels and placeholder + "scan.label.worldserver": "Serveur de monde", + "scan.label.authserver": "Serveur de connexion", + "scan.label.database_content": "Bases de données connexion / personnages / monde", + "scan.label.companions": "Compagnons CoA (bots)", + "scan.label.client": "Client du jeu", + "placeholder.soon": "Cette section sera développée dans une prochaine version.", }; export default fr; diff --git a/src/i18n/locales/ru.ts b/src/i18n/locales/ru.ts index c75e753..8fbba7c 100644 --- a/src/i18n/locales/ru.ts +++ b/src/i18n/locales/ru.ts @@ -433,6 +433,70 @@ const ru: Partial> = { // Friends line "fr.copyLine": "Скопировать строку", + + // Diagnostics checks + "dg.title.files": "Файлы сервера", + "dg.title.missing_parts": "Отсутствующие части", + "dg.title.mysql": "База данных", + "dg.title.auth": "Сервер входа", + "dg.title.world": "Игровой мир", + "dg.title.configs": "Конфигурация", + "dg.title.config_values": "Значения настроек", + "dg.title.disk": "Свободное место на диске", + "dg.title.permissions": "Права доступа", + "dg.title.client": "Клиент игры", + "dg.title.exposure": "Закрытые службы", + "dg.files.ok": "Найдены все ожидаемые части сервера.", + "dg.files.partial": "Некоторых частей сервера не хватает.", + "dg.files.custom": "Это нестандартная сборка сервера; часть функций ограничена.", + "dg.files.bad": "Эта папка не похожа на сервер CoA.", + "dg.svc.running": "Работает", + "dg.svc.port": "Порт {port} занят другой программой (процесс {pid}).", + "dg.svc.starting": "Запускается, пока не отвечает.", + "dg.svc.stopped": "Не запущено.", + "dg.configs.ok": "Файлы конфигурации читаются.", + "dg.configs.bad": "Не удаётся прочитать: {files}", + "dg.values.bad": "Недопустимые значения у: {keys}", + "dg.disk.ok": "Свободно {gb} ГБ", + "dg.disk.low": "Свободно только {gb} ГБ; для резервных копий и обновлений нужно место.", + "dg.perm.ok": "В папку сервера можно записывать.", + "dg.perm.bad": "Менеджер не может записывать в папку сервера (выберите другое место или один раз запустите от имени администратора).", + "dg.client.missing": "Сохранённая папка игры не найдена; выберите её заново в Настройках.", + "dg.exposure.ok": "База данных и консоль сервера недоступны из сети.", + "dg.exposure.bad": "Доступно из сети: {what}.", + + // Update steps + "ustep.Starting": "Запуск", + "ustep.Checking the update": "Проверка обновления", + "ustep.Downloading the update": "Загрузка обновления", + "ustep.Verifying the update": "Проверка подлинности обновления", + "ustep.Making sure the server is stopped": "Убеждаюсь, что сервер остановлен", + "ustep.Saving a recovery point": "Сохранение точки восстановления", + "ustep.Applying the update": "Применение обновления", + "ustep.Updating the database": "Обновление базы данных", + "ustep.Starting the updated server": "Запуск обновлённого сервера", + "ustep.Finishing": "Завершение", + "ustep.Undoing the update": "Откат обновления", + "ustep.Done": "Готово", + + // Companion sizes + "comp.size.small": "Малый", + "comp.size.medium": "Средний", + "comp.size.large": "Большой", + "comp.warnHardware": "Для {n} компаньонов может не хватить процессора и памяти этого компьютера (ядер — {cores}, памяти — {ram} ГБ).", + "comp.warnMemory": "Сначала освободите память: большую её часть занимают другие программы.", + + // Friends notes + "fr.note.forwarded": "Роутеру отправлена просьба пробросить игровые порты.", + "fr.note.manual": "Ваш роутер не поддерживает автоматическую настройку; пробросьте два игровых порта вручную или используйте частную сеть.", + + // Import labels and placeholder + "scan.label.worldserver": "Игровой сервер (мир)", + "scan.label.authserver": "Сервер входа", + "scan.label.database_content": "Базы данных входа, персонажей и мира", + "scan.label.companions": "Компаньоны CoA (боты)", + "scan.label.client": "Клиент игры", + "placeholder.soon": "Этот раздел появится в одном из следующих выпусков.", }; export default ru; diff --git a/src/i18n/schema/de.json b/src/i18n/schema/de.json new file mode 100644 index 0000000..4c9c669 --- /dev/null +++ b/src/i18n/schema/de.json @@ -0,0 +1,513 @@ +{ + "categories": { + "bots.general": "Allgemein", + "bots.population": "Population", + "bots.login": "Anmeldung", + "bots.roles": "Rollen", + "bots.openworld": "Offene Welt", + "bots.quests": "Quests", + "bots.combat": "Kampf", + "bots.dungeon": "Dungeonsuche", + "bots.battlegrounds": "Schlachtfelder", + "bots.social": "Soziales Verhalten", + "bots.advanced": "Erweitert", + "server.gameplay": "Spielablauf", + "server.rates": "Raten", + "server.characters": "Charaktere", + "server.world": "Welt", + "server.network": "Netzwerk", + "server.accounts": "Konten", + "server.logging": "Protokolle", + "server.performance": "Leistung", + "server.advanced": "Erweitert" + }, + "units": { + "ms": "ms", + "%": "%", + "yards": "Yards", + "levels": "Stufen", + "x": "×", + "min": "Min.", + "copper": "Kupfer" + }, + "settings": { + "CoaBots.RandomSpawn.DefaultCount": { + "t": "Bots pro Erstellungsbefehl", + "d": "Wie viele Bots der Erstellungsbefehl anlegt, wenn du keine Zahl angibst." + }, + "CoaBots.RandomSpawn.MaxCount": { + "t": "Größte einzelne Erstellung", + "d": "Sicherheitsgrenze für einen Erstellungsbefehl. Sehr große Mengen können den Server kurz einfrieren lassen; erhöhe den Wert daher nur, wenn sonst niemand spielt." + }, + "CoaBots.LeveledSpawn.Brackets": { + "t": "Stufenmix neuer Bots", + "d": "Wie neue Level-Bots auf Stufen verteilt werden, als Bereiche mit Gewichten (1-20:40 bedeutet 40 Teile Bots zwischen Stufe 1 und 20)." + }, + "CoaBots.RandomSpawn.AutoLogin": { + "t": "Neue Bots sofort online bringen", + "d": "Neu erstellte Bots melden sich sofort an, statt in der Datenbank zu warten." + }, + "CoaBots.RandomSpawn.AccountPrefix": { + "t": "Namenspräfix der Bot-Konten", + "d": "Bots leben auf Konten, deren Name mit diesem Präfix beginnt. Wird es geändert, melden sich vorhandene Bots nicht mehr automatisch an." + }, + "CoaBots.RandomSpawn.BatchSize": { + "t": "Bots pro Erstellungsschritt", + "d": "Die Erstellung wird zeitlich gestreckt, damit der Server flüssig bleibt. Höhere Werte sind schneller, können aber Ruckler verursachen." + }, + "CoaBots.RandomSpawn.BatchIntervalMs": { + "t": "Pause zwischen Erstellungsschritten", + "d": "Zeit zwischen den Erstellungsschritten. Niedrigere Werte sind schneller, können aber Ruckler verursachen." + }, + "CoaBots.AutoLoginOnStartup": { + "t": "Automatische Bot-Anmeldung", + "d": "Vorhandene Bots melden sich bei jedem Serverstart selbst an." + }, + "CoaBots.AutoLogin.MaxCount": { + "t": "Maximale Bots online", + "d": "Die höchste Anzahl an Bots, die sich beim Start automatisch anmelden." + }, + "CoaBots.AutoLogin.BatchSize": { + "t": "Bots pro Anmeldeschritt", + "d": "Anmeldungen werden zeitlich gestreckt. Höhere Werte bringen Bots schneller online, belasten den Server aber stärker." + }, + "CoaBots.AutoLogin.BatchIntervalMs": { + "t": "Pause zwischen Anmeldeschritten", + "d": "Zeit zwischen den Anmeldeschritten." + }, + "CoaBots.SpecBalance.TankTargetPct": { + "t": "Zielanteil an Tanks", + "d": "Anteil der Bots, die Tanks sein sollen." + }, + "CoaBots.SpecBalance.HealerTargetPct": { + "t": "Zielanteil an Heilern", + "d": "Anteil der Bots, die Heiler sein sollen." + }, + "CoaBots.TalentBuildsPath": { + "t": "Talentdatendatei", + "d": "Wo die Talent-Builds der Community gespeichert sind. Leer lassen, um die eingebaute Suche zu nutzen." + }, + "CoaBots.World.Enable": { + "t": "Bots streifen durch die Welt", + "d": "Untätige Bots erledigen Besorgungen: Sie besuchen Stadtdienste, reisen zu Sammel- oder Grind-Gebieten oder wandern ein wenig umher." + }, + "CoaBots.WorldBrain.Enable": { + "t": "Quest-KI", + "d": "Bots nehmen Quests selbstständig an und erledigen sie. Wenn ausgeschaltet, sammeln, angeln, grinden und wandern Bots nur." + }, + "CoaBots.World.ServiceRadius": { + "t": "Suchradius für Stadtdienste", + "d": "Wie weit ein Bot nach Händlern und Briefkästen sucht." + }, + "CoaBots.World.AreaRadius": { + "t": "Radius des Besorgungsgebiets", + "d": "Wie weit ein Bot nach Sammel- oder Grind-Gebieten sucht." + }, + "CoaBots.World.ThinkIntervalMs": { + "t": "Prüfintervall für Besorgungen", + "d": "Wie oft jeder Bot seine Besorgung neu überdenkt." + }, + "CoaBots.World.IdleBeforeErrandMs": { + "t": "Leerlaufzeit vor einer Besorgung", + "d": "Wie lange ein Bot nichts zu tun finden muss, bevor er eine Besorgung beginnt." + }, + "CoaBots.World.VerboseLog": { + "t": "Ausführliches Besorgungsprotokoll", + "d": "Schreibt jeden Schritt einer Besorgung ins Protokoll. Nützlich zur Fehlersuche, bei vielen Bots aber sehr laut." + }, + "CoaBots.Combat.VerboseLog": { + "t": "Ausführliches Kampfprotokoll", + "d": "Schreibt Kampfentscheidungen ins Protokoll. Sehr laut; nur einschalten, wenn du ein bestimmtes Problem suchst." + }, + "CoaBots.Profile.IntentMinMs": { + "t": "Kürzeste Aktivität", + "d": "Die kürzeste Zeit, die ein Bot bei einer Art von Aktivität bleibt." + }, + "CoaBots.Profile.IntentMaxMs": { + "t": "Längste Aktivität", + "d": "Die längste Zeit, die ein Bot bei einer Art von Aktivität bleibt." + }, + "CoaBots.Grind.SearchRadius": { + "t": "Suchradius fürs Grinden", + "d": "Wie weit ein Bot nach Monstern zum Grinden sucht." + }, + "CoaBots.Grind.MaxLevelAbove": { + "t": "Höchste Monsterstufe fürs Grinden", + "d": "Um wie viele Stufen über sich selbst ein Bot beim Grinden kämpft." + }, + "CoaBots.Healer.CriticalHealPct": { + "t": "Schwelle für Notheilung", + "d": "Heiler wechseln zu ihren stärksten Heilungen, wenn die Gesundheit eines Verbündeten darunter fällt." + }, + "CoaBots.WorldBrain.SearchRadius": { + "t": "Suchradius für Ziele", + "d": "Wie weit ein Bot innerhalb eines Zielgebiets nach Questzielen sucht." + }, + "CoaBots.WorldBrain.EngageRange": { + "t": "Angriffsentfernung", + "d": "Entfernung, ab der ein Bot einen Quest-Gegner bekämpft." + }, + "CoaBots.WorldBrain.MountDistanceMin": { + "t": "Aufsitzen ab (Min.)", + "d": "Jeder Bot sitzt bei Reisen auf, die länger sind als eine persönliche Entfernung, die zwischen diesem Wert und dem Maximum gewählt wird." + }, + "CoaBots.WorldBrain.MountDistanceMax": { + "t": "Aufsitzen ab (Max.)", + "d": "Oberes Ende der persönlichen Aufsitzentfernung." + }, + "CoaBots.WorldBrain.TaxiMinDistance": { + "t": "Flugrouten nutzen ab", + "d": "Reisen, die länger sind, nutzen eine Flugroute, wenn der Bot eine kennt." + }, + "CoaBots.WorldBrain.SessionBreaks": { + "t": "Pausen einlegen", + "d": "Bots wechseln Questen mit ein paar Minuten Stadtleben ab, wie ein Spieler." + }, + "CoaBots.WorldBrain.GatherDetours": { + "t": "Kräuter und Erz in der Nähe sammeln", + "d": "Sammler weichen vom Weg ab, wenn direkt daneben ein Vorkommen liegt." + }, + "CoaBots.WorldBrain.MaxActiveQuests": { + "t": "Maximale aktive Quests", + "d": "Wie viele Quests ein Bot gleichzeitig trägt." + }, + "CoaBots.WorldBrain.AcceptEliteQuests": { + "t": "Elite-Quests annehmen", + "d": "Einzelne Bots übernehmen Elite-Quests. Standardmäßig aus, weil sie diese allein meist nicht schaffen." + }, + "CoaBots.WorldBrain.QuestLevelBelow": { + "t": "Quests unter der eigenen Stufe", + "d": "Um wie viele Stufen unter sich selbst ein Bot noch Quests annimmt." + }, + "CoaBots.WorldBrain.QuestLevelAbove": { + "t": "Quests über der eigenen Stufe", + "d": "Um wie viele Stufen über sich selbst ein Bot noch Quests annimmt." + }, + "CoaBots.WorldBrain.MaxMobLevelAbove": { + "t": "Höchste Stufe von Quest-Monstern", + "d": "Wie weit über seiner Stufe ein Quest-Monster sein darf." + }, + "CoaBots.WorldBrain.MaxObjectiveDistance": { + "t": "Am weitesten entferntes Questziel", + "d": "Quests, deren Ziele weiter entfernt sind, werden nicht angenommen." + }, + "CoaBots.WorldBrain.GiverSearchRadius": { + "t": "Suchradius für Questgeber", + "d": "Wie weit ein Bot nach Questgebern sucht." + }, + "CoaBots.WorldBrain.MaxBadAreasPerObjective": { + "t": "Versuchte Gebiete pro Ziel", + "d": "Wie viele Gebiete ein Bot aufgibt, bevor er die Quest zurückstellt." + }, + "CoaBots.WorldBrain.QuestSuspendMs": { + "t": "Zurückstellzeit (kurz)", + "d": "Wie lange eine Quest zurückgestellt wird, nachdem der Bot sie aufgegeben hat." + }, + "CoaBots.WorldBrain.QuestSuspendMaxMs": { + "t": "Zurückstellzeit (lang)", + "d": "Die längste Zeit, die eine Quest nach wiederholtem Scheitern zurückgestellt bleiben kann." + }, + "CoaBots.LfgFill.Enable": { + "t": "Bot-Auffüllung der Dungeonsuche", + "d": "Wenn du allein für einen Dungeon anstehst, übernehmen Bots die fehlenden Rollen Tank, Heiler und Schaden." + }, + "CoaBots.AutoQueueDungeon.Enable": { + "t": "Bots stellen sich selbst für Dungeons an", + "d": "Experimentell: Untätige Tank-Bots stellen sich selbst für einen Dungeon an, und die Auffüllung oben vervollständigt die Gruppe." + }, + "CoaBots.BGFill.Enable": { + "t": "Bot-Auffüllung für Schlachtfelder", + "d": "Wenn jemand für ein Schlachtfeld ansteht, werden beide Teams mit Bots aufgefüllt, damit das Spiel sofort beginnt." + }, + "CoaBots.BGFill.TargetPlayersPerTeam": { + "t": "Teamgröße auf Schlachtfeldern", + "d": "Bis zu wie vielen Bots pro Team aufgefüllt wird. 0 bedeutet ein volles Team für dieses Schlachtfeld." + }, + "CoaBots.WorldBrain.HelpOthers": { + "t": "Bots helfen Spielern in der Nähe", + "d": "Ein vorbeikommender Bot steigt in einen Kampf ein, den ein befreundeter Spieler verliert, ohne dessen Beute oder Anrechnung zu nehmen." + }, + "CoaBots.WorldBrain.HelpRadius": { + "t": "Hilfsentfernung", + "d": "Wie nah ein Bot sein muss, um in einen Kampf einzugreifen." + }, + "CoaBots.WorldBrain.HelpHealthPct": { + "t": "Helfen unter Gesundheit", + "d": "Bots helfen, wenn die Gesundheit des kämpfenden Spielers darunter liegt." + }, + "CoaBots.WorldBrain.ResurrectOthers": { + "t": "Bots beleben gefallene Spieler", + "d": "Bots, die einen Wiederbelebungszauber kennen, beleben befreundete Leichen." + }, + "CoaBots.WorldBrain.TemporaryParties": { + "t": "Vorübergehende Bot-Gruppen", + "d": "Bots ähnlicher Stufe mit derselben Quest tun sich kurz zusammen." + }, + "CoaBots.WorldBrain.PartyMaxSize": { + "t": "Größe vorübergehender Gruppen", + "d": "Größte vorübergehende Gruppe." + }, + "CoaBots.WorldBrain.PartyRadius": { + "t": "Entfernung zur Gruppenbildung", + "d": "Wie nah Bots sein müssen, um sich zusammenzutun." + }, + "CoaBots.WorldBrain.PartyMinMinutes": { + "t": "Kürzeste Gruppendauer", + "d": "Mindestdauer einer vorübergehenden Gruppe." + }, + "CoaBots.WorldBrain.PartyMaxMinutes": { + "t": "Längste Gruppendauer", + "d": "Höchstdauer einer vorübergehenden Gruppe." + }, + "CoaBots.WorldBrain.PlannerMinMs": { + "t": "Planerintervall (Min.)", + "d": "Kürzeste Zeit zwischen den Planungsdurchläufen eines Bots." + }, + "CoaBots.WorldBrain.PlannerMaxMs": { + "t": "Planerintervall (Max.)", + "d": "Längste Zeit zwischen den Planungsdurchläufen eines Bots." + }, + "CoaBots.WorldBrain.ScanMinMs": { + "t": "Zielsuchintervall (Min.)", + "d": "Kürzeste Zeit zwischen Zielsuchen." + }, + "CoaBots.WorldBrain.ScanMaxMs": { + "t": "Zielsuchintervall (Max.)", + "d": "Längste Zeit zwischen Zielsuchen." + }, + "CoaBots.WorldBrain.SearchTimeoutMs": { + "t": "Zeitlimit der Gebietssuche", + "d": "Wie lange ein Bot ein leeres Gebiet absucht, bevor er ein anderes versucht." + }, + "CoaBots.WorldBrain.ApproachTimeoutMs": { + "t": "Zeitlimit der Annäherung", + "d": "Wie lange ein Bot zu einem beanspruchten Ziel läuft." + }, + "CoaBots.WorldBrain.TravelTimeoutMs": { + "t": "Zeitlimit der Reise", + "d": "Wie lange eine ganze Reise in ein Gebiet dauern darf." + }, + "CoaBots.WorldBrain.Weight.TravelPer100Yards": { + "t": "Präferenzgewicht: TravelPer100Yards", + "d": "Wie stark Bots diesen Faktor gewichten, wenn sie entscheiden, was sie als Nächstes tun. Nur ändern, wenn du den Planer kennst." + }, + "CoaBots.WorldBrain.Weight.CrowdPerBot": { + "t": "Präferenzgewicht: CrowdPerBot", + "d": "Wie stark Bots diesen Faktor gewichten, wenn sie entscheiden, was sie als Nächstes tun. Nur ändern, wenn du den Planer kennst." + }, + "CoaBots.WorldBrain.Weight.Overlap": { + "t": "Präferenzgewicht: Overlap", + "d": "Wie stark Bots diesen Faktor gewichten, wenn sie entscheiden, was sie als Nächstes tun. Nur ändern, wenn du den Planer kennst." + }, + "CoaBots.WorldBrain.Weight.TurnIn": { + "t": "Präferenzgewicht: TurnIn", + "d": "Wie stark Bots diesen Faktor gewichten, wenn sie entscheiden, was sie als Nächstes tun. Nur ändern, wenn du den Planer kennst." + }, + "CoaBots.WorldBrain.Weight.Accept": { + "t": "Präferenzgewicht: Accept", + "d": "Wie stark Bots diesen Faktor gewichten, wenn sie entscheiden, was sie als Nächstes tun. Nur ändern, wenn du den Planer kennst." + }, + "CoaBots.WorldBrain.Weight.AreaOccupancy": { + "t": "Präferenzgewicht: AreaOccupancy", + "d": "Wie stark Bots diesen Faktor gewichten, wenn sie entscheiden, was sie als Nächstes tun. Nur ändern, wenn du den Planer kennst." + }, + "CoaBots.WorldBrain.Weight.TargetReserved": { + "t": "Präferenzgewicht: TargetReserved", + "d": "Wie stark Bots diesen Faktor gewichten, wenn sie entscheiden, was sie als Nächstes tun. Nur ändern, wenn du den Planer kennst." + }, + "Rate.XP.Kill": { + "t": "Erfahrung durch Kills", + "d": "Multiplikator für Erfahrung durch das Töten von Monstern. 1 ist normal." + }, + "Rate.XP.Quest": { + "t": "Erfahrung durch Quests", + "d": "Multiplikator für Erfahrung aus Quests." + }, + "Rate.XP.Quest.DF": { + "t": "Erfahrung durch tägliche Quests / Dungeonsuche", + "d": "Multiplikator für Erfahrung aus Quests der Dungeonsuche." + }, + "Rate.XP.Explore": { + "t": "Erfahrung durch Erkunden", + "d": "Multiplikator für Erfahrung beim Entdecken neuer Gebiete." + }, + "Rate.Drop.Item.Normal": { + "t": "Gegenstands-Droprate", + "d": "Multiplikator dafür, wie oft Gegenstände normaler Qualität fallen." + }, + "Rate.Drop.Money": { + "t": "Gold-Droprate", + "d": "Multiplikator für das Gold, das Monster fallen lassen." + }, + "Rate.Honor": { + "t": "Ehregewinn", + "d": "Multiplikator für verdiente Ehrenpunkte." + }, + "Rate.Reputation.Gain": { + "t": "Rufgewinn", + "d": "Multiplikator für verdienten Ruf." + }, + "Rate.Rest.InGame": { + "t": "Ruhebonus beim Spielen", + "d": "Geschwindigkeit, mit der Ruhe-Erfahrung beim Spielen aufgebraucht wird." + }, + "Rate.Creature.Normal.Damage": { + "t": "Monsterschaden", + "d": "Multiplikator für den Schaden normaler Monster. Verändert den Schwierigkeitsgrad stark." + }, + "Rate.Creature.Normal.HP": { + "t": "Monstergesundheit", + "d": "Multiplikator für die Gesundheit normaler Monster. Verändert den Schwierigkeitsgrad stark." + }, + "PlayerLimit": { + "t": "Maximale Spielerzahl", + "d": "Wie viele Spieler gleichzeitig online sein können. 0 bedeutet kein Limit." + }, + "GameType": { + "t": "Realmtyp", + "d": "Der in der Realmliste angezeigte Realmtyp." + }, + "RealmZone": { + "t": "Realmzone", + "d": "Die Sprach- bzw. Regionsgruppe des Realms, die Clients angezeigt wird." + }, + "PlayerSaveInterval": { + "t": "Autospeicher-Intervall", + "d": "Wie oft Spielercharaktere gespeichert werden, solange sie online sind." + }, + "CharactersPerAccount": { + "t": "Charaktere pro Konto", + "d": "Maximale Zahl an Charakteren, die ein Konto über alle Realms hat." + }, + "CharactersPerRealm": { + "t": "Charaktere pro Realm", + "d": "Maximale Zahl an Charakteren, die ein Konto auf diesem Realm hat." + }, + "StartPlayerLevel": { + "t": "Startstufe", + "d": "Stufe, mit der neue Charaktere beginnen." + }, + "StartPlayerMoney": { + "t": "Startgold", + "d": "Kupfer, mit dem neue Charaktere beginnen (10000 Kupfer = 1 Gold)." + }, + "MaxPlayerLevel": { + "t": "Maximale Stufe", + "d": "Höchste Stufe, die ein Charakter erreichen kann. Der Spielclient unterstützt nur 80." + }, + "SkipCinematics": { + "t": "Intro-Videos überspringen", + "d": "Ob neue Charaktere ihr Intro-Video sehen." + }, + "DurabilityLoss.OnDeath": { + "t": "Haltbarkeitsverlust beim Tod", + "d": "Prozent der Haltbarkeit von Gegenständen, die beim Tod verloren gehen." + }, + "Death.SicknessLevel": { + "t": "Wiederbelebungsschwäche bis Stufe", + "d": "Charaktere über dieser Stufe erhalten Wiederbelebungsschwäche. -10 schaltet sie aus." + }, + "LeaveGroupOnLogout.Enabled": { + "t": "Gruppe beim Abmelden verlassen", + "d": "Spieler werden aus ihrer Gruppe entfernt, wenn sie sich abmelden." + }, + "GM.LoginState": { + "t": "GM-Modus bei der Anmeldung", + "d": "Ob Gamemaster mit eingeschaltetem GM-Modus starten." + }, + "AllowTwoSide.Accounts": { + "t": "Beide Fraktionen auf einem Konto", + "d": "Ein Konto darf Allianz- und Horde-Charaktere haben." + }, + "AllowTwoSide.Interaction.Chat": { + "t": "Fraktionsübergreifender Chat", + "d": "Allianz- und Horde-Spieler können miteinander sprechen." + }, + "AutoBroadcast.On": { + "t": "Automatische Ankündigungen", + "d": "Sendet die in der Datenbank gespeicherten Nachrichten in regelmäßigen Abständen." + }, + "AutoBroadcast.Timer": { + "t": "Ankündigungsintervall", + "d": "Zeit zwischen automatischen Ankündigungen." + }, + "Warden.Enabled": { + "t": "Anti-Cheat (Warden)", + "d": "Aktiviert die Anti-Cheat-Prüfung des Clients. Auf einem privaten Server meist unnötig." + }, + "MapUpdateInterval": { + "t": "Karten-Aktualisierungsintervall", + "d": "Wie oft die Welt Karten aktualisiert. Niedriger ist flüssiger, braucht aber mehr CPU." + }, + "MinWorldUpdateTime": { + "t": "Minimale Weltaktualisierungszeit", + "d": "Kürzeste Zeit zwischen Weltaktualisierungen. Erhöhe sie, um die CPU-Last zu senken." + }, + "ThreadPool": { + "t": "Arbeitsthreads", + "d": "Anzahl der Hintergrund-Arbeitsthreads. Mehr hilft bei großen Spielerzahlen." + }, + "Network.Threads": { + "t": "Netzwerk-Threads", + "d": "Threads, die Spielerverbindungen verarbeiten. Für kleine Server genügt einer." + }, + "Ra.Enable": { + "t": "Remote-Konsole", + "d": "Erlaubt dem Manager und Skripten, Befehle an den Server zu senden. Sie lauscht nur auf diesem Computer; lass es dabei." + }, + "Ra.IP": { + "t": "Adresse der Remote-Konsole", + "d": "Adresse, auf der die Remote-Konsole lauscht. Behalte 127.0.0.1, damit sie nicht aus dem Internet erreichbar ist." + }, + "Updates.EnableDatabases": { + "t": "Automatische Datenbank-Updates", + "d": "Erlaubt dem Server, seine Datenbanken beim Start selbst zu ändern. Lass es auf 0: Der Manager wendet Datenbank-Updates sicher an und verfolgt sie." + } + }, + "options": { + "GameType.0": "Normal", + "GameType.1": "Spieler gegen Spieler", + "GameType.6": "Rollenspiel", + "GameType.8": "Rollenspiel + PvP", + "SkipCinematics.0": "Alle zeigen", + "SkipCinematics.1": "Für alle außer dem ersten Charakter überspringen", + "SkipCinematics.2": "Alle überspringen", + "GM.LoginState.0": "Aus", + "GM.LoginState.1": "An", + "GM.LoginState.2": "Wie beim letzten Mal" + }, + "presets": { + "balanced": { + "t": "Ausgewogen", + "d": "Die empfohlene Alltagseinstellung: Quests, Dungeon- und Schlachtfeld-Auffüllung an, ruhige Protokolle." + }, + "solo-friendly": { + "t": "Solo-freundlich", + "d": "Bots, die dir helfen und deine Gruppen auffüllen, mit einer kleinen, ruhigen Population." + }, + "living-world": { + "t": "Lebendige Welt", + "d": "Eine belebtere Welt: mehr Bots, Pausen, Sammel-Abstecher und vorübergehende Gruppen." + }, + "performance": { + "t": "Leistung", + "d": "Weniger Bots und weniger Bot-Denken, für schwächere Computer." + }, + "vanilla": { + "t": "Standardraten", + "d": "Alles in normaler Geschwindigkeit (×1)." + }, + "relaxed": { + "t": "Entspannt", + "d": "Schnelleres Leveln und mehr Beute für Gelegenheitsspieler (×2 / ×3)." + }, + "fast": { + "t": "Schnell", + "d": "Schneller Fortschritt für Tests oder kurze Sitzungen (×5)." + }, + "defaults": { + "t": "Empfohlene Standardwerte", + "d": "Alle Einstellungen kehren zu ihren Standardwerten zurück." + } + } +} \ No newline at end of file diff --git a/src/i18n/schema/es.json b/src/i18n/schema/es.json new file mode 100644 index 0000000..ffa69be --- /dev/null +++ b/src/i18n/schema/es.json @@ -0,0 +1,513 @@ +{ + "categories": { + "bots.general": "General", + "bots.population": "Población", + "bots.login": "Inicio de sesión", + "bots.roles": "Roles", + "bots.openworld": "Mundo abierto", + "bots.quests": "Misiones", + "bots.combat": "Combate", + "bots.dungeon": "Buscador de mazmorras", + "bots.battlegrounds": "Campos de batalla", + "bots.social": "Comportamiento social", + "bots.advanced": "Avanzado", + "server.gameplay": "Jugabilidad", + "server.rates": "Tasas", + "server.characters": "Personajes", + "server.world": "Mundo", + "server.network": "Red", + "server.accounts": "Cuentas", + "server.logging": "Registros", + "server.performance": "Rendimiento", + "server.advanced": "Avanzado" + }, + "units": { + "ms": "ms", + "%": "%", + "yards": "yardas", + "levels": "niveles", + "x": "×", + "min": "min", + "copper": "cobre" + }, + "settings": { + "CoaBots.RandomSpawn.DefaultCount": { + "t": "Bots creados por comando", + "d": "Cuántos bots crea el comando de creación cuando no indicas un número." + }, + "CoaBots.RandomSpawn.MaxCount": { + "t": "Mayor creación individual", + "d": "Límite de seguridad para un comando de creación. Los lotes muy grandes pueden congelar el servidor un momento, así que súbelo solo cuando nadie más esté jugando." + }, + "CoaBots.LeveledSpawn.Brackets": { + "t": "Reparto de niveles de los bots nuevos", + "d": "Cómo se reparten por niveles los nuevos bots que suben de nivel, como rangos con pesos (1-20:40 significa 40 partes de bots entre los niveles 1 y 20)." + }, + "CoaBots.RandomSpawn.AutoLogin": { + "t": "Conectar enseguida a los bots nuevos", + "d": "Los bots recién creados inician sesión de inmediato en lugar de esperar en la base de datos." + }, + "CoaBots.RandomSpawn.AccountPrefix": { + "t": "Prefijo de los nombres de cuenta de bots", + "d": "Los bots viven en cuentas cuyo nombre empieza por este prefijo. Cambiarlo hace que los bots existentes dejen de conectarse automáticamente." + }, + "CoaBots.RandomSpawn.BatchSize": { + "t": "Bots creados por paso", + "d": "La creación se reparte en el tiempo para que el servidor vaya fluido. Valores altos son más rápidos, pero pueden causar tirones." + }, + "CoaBots.RandomSpawn.BatchIntervalMs": { + "t": "Pausa entre pasos de creación", + "d": "Tiempo entre los pasos de creación. Valores bajos son más rápidos, pero pueden causar tirones." + }, + "CoaBots.AutoLoginOnStartup": { + "t": "Conexión automática de bots", + "d": "Los bots existentes inician sesión solos cada vez que arranca el servidor." + }, + "CoaBots.AutoLogin.MaxCount": { + "t": "Máximo de bots conectados", + "d": "El mayor número de bots que inician sesión automáticamente al arrancar." + }, + "CoaBots.AutoLogin.BatchSize": { + "t": "Bots que se conectan por paso", + "d": "Las conexiones se reparten en el tiempo. Valores altos conectan bots más rápido, pero cargan más el servidor." + }, + "CoaBots.AutoLogin.BatchIntervalMs": { + "t": "Pausa entre pasos de conexión", + "d": "Tiempo entre los pasos de conexión." + }, + "CoaBots.SpecBalance.TankTargetPct": { + "t": "Proporción objetivo de tanques", + "d": "Proporción de bots que deben ser tanques." + }, + "CoaBots.SpecBalance.HealerTargetPct": { + "t": "Proporción objetivo de sanadores", + "d": "Proporción de bots que deben ser sanadores." + }, + "CoaBots.TalentBuildsPath": { + "t": "Archivo de datos de talentos", + "d": "Dónde se guardan las builds de talentos de la comunidad. Déjalo vacío para usar la búsqueda integrada." + }, + "CoaBots.World.Enable": { + "t": "Los bots vagan por el mundo", + "d": "Los bots inactivos hacen recados: visitan servicios de la ciudad, viajan a zonas de recolección o de farmeo o deambulan un poco." + }, + "CoaBots.WorldBrain.Enable": { + "t": "IA de misiones", + "d": "Los bots aceptan y completan misiones por su cuenta. Si se apaga, los bots solo recolectan, pescan, farmean y deambulan." + }, + "CoaBots.World.ServiceRadius": { + "t": "Radio de búsqueda de servicios de la ciudad", + "d": "Hasta dónde busca un bot vendedores y buzones." + }, + "CoaBots.World.AreaRadius": { + "t": "Radio de la zona de recados", + "d": "Hasta dónde busca un bot zonas de recolección o de farmeo." + }, + "CoaBots.World.ThinkIntervalMs": { + "t": "Intervalo de revisión de recados", + "d": "Con qué frecuencia cada bot reconsidera su recado." + }, + "CoaBots.World.IdleBeforeErrandMs": { + "t": "Inactividad antes de un recado", + "d": "Cuánto tiempo debe un bot no encontrar nada que hacer antes de empezar un recado." + }, + "CoaBots.World.VerboseLog": { + "t": "Registro detallado de recados", + "d": "Escribe cada paso de los recados en el registro. Útil para depurar, ruidoso con muchos bots." + }, + "CoaBots.Combat.VerboseLog": { + "t": "Registro detallado de combate", + "d": "Escribe las decisiones de combate en el registro. Muy ruidoso; actívalo solo mientras buscas un problema concreto." + }, + "CoaBots.Profile.IntentMinMs": { + "t": "Actividad más corta", + "d": "El menor tiempo que un bot se mantiene en un mismo tipo de actividad." + }, + "CoaBots.Profile.IntentMaxMs": { + "t": "Actividad más larga", + "d": "El mayor tiempo que un bot se mantiene en un mismo tipo de actividad." + }, + "CoaBots.Grind.SearchRadius": { + "t": "Radio de búsqueda para farmear", + "d": "Hasta dónde busca un bot monstruos para farmear." + }, + "CoaBots.Grind.MaxLevelAbove": { + "t": "Nivel máximo de monstruo para farmear", + "d": "Cuántos niveles por encima del suyo combate un bot al farmear." + }, + "CoaBots.Healer.CriticalHealPct": { + "t": "Umbral de curación de emergencia", + "d": "Los sanadores pasan a sus curas más fuertes cuando la salud de un aliado cae por debajo de este valor." + }, + "CoaBots.WorldBrain.SearchRadius": { + "t": "Radio de búsqueda de objetivos", + "d": "Hasta dónde examina un bot en busca de objetivos de misión dentro de una zona de objetivo." + }, + "CoaBots.WorldBrain.EngageRange": { + "t": "Distancia de enfrentamiento", + "d": "Distancia a la que un bot empieza a combatir a un monstruo de misión." + }, + "CoaBots.WorldBrain.MountDistanceMin": { + "t": "Montar a partir de (mín.)", + "d": "Cada bot monta en viajes más largos que una distancia personal elegida entre este valor y el máximo." + }, + "CoaBots.WorldBrain.MountDistanceMax": { + "t": "Montar a partir de (máx.)", + "d": "Extremo superior de la distancia personal para montar." + }, + "CoaBots.WorldBrain.TaxiMinDistance": { + "t": "Usar rutas de vuelo a partir de", + "d": "Los viajes más largos usan una ruta de vuelo si el bot conoce alguna." + }, + "CoaBots.WorldBrain.SessionBreaks": { + "t": "Hacer descansos", + "d": "Los bots alternan las misiones con unos minutos de vida en la ciudad, como haría un jugador." + }, + "CoaBots.WorldBrain.GatherDetours": { + "t": "Recolectar hierbas y minerales cercanos", + "d": "Los recolectores se desvían de su camino por un nodo justo al lado." + }, + "CoaBots.WorldBrain.MaxActiveQuests": { + "t": "Máximo de misiones activas", + "d": "Cuántas misiones lleva un bot a la vez." + }, + "CoaBots.WorldBrain.AcceptEliteQuests": { + "t": "Aceptar misiones de élite", + "d": "Los bots en solitario aceptan misiones de élite. Desactivado por defecto porque normalmente no pueden completarlas solos." + }, + "CoaBots.WorldBrain.QuestLevelBelow": { + "t": "Misiones por debajo de su nivel", + "d": "Cuántos niveles por debajo del suyo sigue aceptando misiones un bot." + }, + "CoaBots.WorldBrain.QuestLevelAbove": { + "t": "Misiones por encima de su nivel", + "d": "Cuántos niveles por encima del suyo sigue aceptando misiones un bot." + }, + "CoaBots.WorldBrain.MaxMobLevelAbove": { + "t": "Nivel máximo del monstruo de misión", + "d": "Cuánto por encima de su nivel puede estar un monstruo de misión." + }, + "CoaBots.WorldBrain.MaxObjectiveDistance": { + "t": "Objetivo de misión más lejano", + "d": "No se aceptan las misiones cuyos objetivos estén más lejos." + }, + "CoaBots.WorldBrain.GiverSearchRadius": { + "t": "Radio de búsqueda de dadores de misiones", + "d": "Hasta dónde busca un bot a quienes dan misiones." + }, + "CoaBots.WorldBrain.MaxBadAreasPerObjective": { + "t": "Zonas probadas por objetivo", + "d": "Cuántas zonas descarta un bot antes de dejar la misión aparcada." + }, + "CoaBots.WorldBrain.QuestSuspendMs": { + "t": "Tiempo aparcada (corto)", + "d": "Cuánto tiempo se aparca una misión después de que el bot renuncie a ella." + }, + "CoaBots.WorldBrain.QuestSuspendMaxMs": { + "t": "Tiempo aparcada (largo)", + "d": "El máximo tiempo que una misión puede quedar aparcada tras fallos repetidos." + }, + "CoaBots.LfgFill.Enable": { + "t": "Relleno con bots del Buscador de mazmorras", + "d": "Cuando te pones en cola solo para una mazmorra, los bots ocupan los roles de tanque, sanador y daño que falten." + }, + "CoaBots.AutoQueueDungeon.Enable": { + "t": "Los bots se ponen en cola para mazmorras solos", + "d": "Experimental: los bots tanque inactivos se ponen en cola para una mazmorra por su cuenta y el relleno anterior completa el grupo." + }, + "CoaBots.BGFill.Enable": { + "t": "Relleno con bots de campos de batalla", + "d": "Cuando alguien se pone en cola para un campo de batalla, ambos equipos se completan con bots para que la partida empiece enseguida." + }, + "CoaBots.BGFill.TargetPlayersPerTeam": { + "t": "Tamaño de equipo en campos de batalla", + "d": "Bots por equipo hasta los que rellenar. 0 significa un equipo completo para ese campo de batalla." + }, + "CoaBots.WorldBrain.HelpOthers": { + "t": "Los bots ayudan a jugadores cercanos", + "d": "Un bot que pasa por allí se une a un combate que un jugador amigo está perdiendo, sin quedarse con su botín ni su crédito." + }, + "CoaBots.WorldBrain.HelpRadius": { + "t": "Distancia de ayuda", + "d": "Lo cerca que debe estar un bot para meterse en un combate." + }, + "CoaBots.WorldBrain.HelpHealthPct": { + "t": "Ayudar por debajo de salud", + "d": "Los bots ayudan cuando la salud del jugador que combate está por debajo de este valor." + }, + "CoaBots.WorldBrain.ResurrectOthers": { + "t": "Los bots resucitan a jugadores caídos", + "d": "Los bots que conocen un hechizo de resurrección reviven cadáveres amigos." + }, + "CoaBots.WorldBrain.TemporaryParties": { + "t": "Grupos temporales de bots", + "d": "Bots de nivel parecido con la misma misión se unen brevemente." + }, + "CoaBots.WorldBrain.PartyMaxSize": { + "t": "Tamaño del grupo temporal", + "d": "El mayor tamaño de un grupo temporal." + }, + "CoaBots.WorldBrain.PartyRadius": { + "t": "Distancia para formar grupo", + "d": "Lo cerca que deben estar los bots para unirse." + }, + "CoaBots.WorldBrain.PartyMinMinutes": { + "t": "Duración mínima del grupo", + "d": "Duración mínima de un grupo temporal." + }, + "CoaBots.WorldBrain.PartyMaxMinutes": { + "t": "Duración máxima del grupo", + "d": "Duración máxima de un grupo temporal." + }, + "CoaBots.WorldBrain.PlannerMinMs": { + "t": "Intervalo del planificador (mín.)", + "d": "El menor tiempo entre las pasadas de planificación de un bot." + }, + "CoaBots.WorldBrain.PlannerMaxMs": { + "t": "Intervalo del planificador (máx.)", + "d": "El mayor tiempo entre las pasadas de planificación de un bot." + }, + "CoaBots.WorldBrain.ScanMinMs": { + "t": "Intervalo de búsqueda de objetivos (mín.)", + "d": "El menor tiempo entre búsquedas de objetivos." + }, + "CoaBots.WorldBrain.ScanMaxMs": { + "t": "Intervalo de búsqueda de objetivos (máx.)", + "d": "El mayor tiempo entre búsquedas de objetivos." + }, + "CoaBots.WorldBrain.SearchTimeoutMs": { + "t": "Límite de tiempo de búsqueda en una zona", + "d": "Cuánto tiempo rastrea un bot una zona vacía antes de probar otra." + }, + "CoaBots.WorldBrain.ApproachTimeoutMs": { + "t": "Límite de tiempo de aproximación", + "d": "Cuánto tiempo camina un bot hacia un objetivo reservado." + }, + "CoaBots.WorldBrain.TravelTimeoutMs": { + "t": "Límite de tiempo de viaje", + "d": "Cuánto puede durar todo un viaje a una zona." + }, + "CoaBots.WorldBrain.Weight.TravelPer100Yards": { + "t": "Peso de preferencia: TravelPer100Yards", + "d": "Cuánto peso dan los bots a este factor al elegir qué hacer a continuación. Cámbialo solo si conoces el planificador." + }, + "CoaBots.WorldBrain.Weight.CrowdPerBot": { + "t": "Peso de preferencia: CrowdPerBot", + "d": "Cuánto peso dan los bots a este factor al elegir qué hacer a continuación. Cámbialo solo si conoces el planificador." + }, + "CoaBots.WorldBrain.Weight.Overlap": { + "t": "Peso de preferencia: Overlap", + "d": "Cuánto peso dan los bots a este factor al elegir qué hacer a continuación. Cámbialo solo si conoces el planificador." + }, + "CoaBots.WorldBrain.Weight.TurnIn": { + "t": "Peso de preferencia: TurnIn", + "d": "Cuánto peso dan los bots a este factor al elegir qué hacer a continuación. Cámbialo solo si conoces el planificador." + }, + "CoaBots.WorldBrain.Weight.Accept": { + "t": "Peso de preferencia: Accept", + "d": "Cuánto peso dan los bots a este factor al elegir qué hacer a continuación. Cámbialo solo si conoces el planificador." + }, + "CoaBots.WorldBrain.Weight.AreaOccupancy": { + "t": "Peso de preferencia: AreaOccupancy", + "d": "Cuánto peso dan los bots a este factor al elegir qué hacer a continuación. Cámbialo solo si conoces el planificador." + }, + "CoaBots.WorldBrain.Weight.TargetReserved": { + "t": "Peso de preferencia: TargetReserved", + "d": "Cuánto peso dan los bots a este factor al elegir qué hacer a continuación. Cámbialo solo si conoces el planificador." + }, + "Rate.XP.Kill": { + "t": "Experiencia por muertes", + "d": "Multiplicador de la experiencia ganada al matar monstruos. 1 es lo normal." + }, + "Rate.XP.Quest": { + "t": "Experiencia por misiones", + "d": "Multiplicador de la experiencia ganada con las misiones." + }, + "Rate.XP.Quest.DF": { + "t": "Experiencia por misiones diarias / Buscador de mazmorras", + "d": "Multiplicador de la experiencia de las misiones del Buscador de mazmorras." + }, + "Rate.XP.Explore": { + "t": "Experiencia por explorar", + "d": "Multiplicador de la experiencia por descubrir nuevas zonas." + }, + "Rate.Drop.Item.Normal": { + "t": "Tasa de botín de objetos", + "d": "Multiplicador de la frecuencia con que caen objetos de calidad normal." + }, + "Rate.Drop.Money": { + "t": "Tasa de botín de oro", + "d": "Multiplicador del oro que sueltan los monstruos." + }, + "Rate.Honor": { + "t": "Ganancia de honor", + "d": "Multiplicador de los puntos de honor obtenidos." + }, + "Rate.Reputation.Gain": { + "t": "Ganancia de reputación", + "d": "Multiplicador de la reputación obtenida." + }, + "Rate.Rest.InGame": { + "t": "Bonificación de descanso al jugar", + "d": "Velocidad a la que se consume la experiencia de descanso mientras juegas." + }, + "Rate.Creature.Normal.Damage": { + "t": "Daño de los monstruos", + "d": "Multiplicador del daño de los monstruos normales. Cambia mucho la dificultad." + }, + "Rate.Creature.Normal.HP": { + "t": "Salud de los monstruos", + "d": "Multiplicador de la salud de los monstruos normales. Cambia mucho la dificultad." + }, + "PlayerLimit": { + "t": "Máximo de jugadores", + "d": "Cuántos jugadores pueden estar conectados a la vez. 0 significa sin límite." + }, + "GameType": { + "t": "Tipo de reino", + "d": "El tipo de reino que se muestra en la lista de reinos." + }, + "RealmZone": { + "t": "Zona del reino", + "d": "El grupo de idioma / región del reino que se muestra a los clientes." + }, + "PlayerSaveInterval": { + "t": "Intervalo de autoguardado", + "d": "Con qué frecuencia se guardan los personajes de los jugadores mientras están conectados." + }, + "CharactersPerAccount": { + "t": "Personajes por cuenta", + "d": "Máximo de personajes que puede tener una cuenta entre todos los reinos." + }, + "CharactersPerRealm": { + "t": "Personajes por reino", + "d": "Máximo de personajes que puede tener una cuenta en este reino." + }, + "StartPlayerLevel": { + "t": "Nivel inicial", + "d": "Nivel con el que empiezan los personajes nuevos." + }, + "StartPlayerMoney": { + "t": "Oro inicial", + "d": "Cobre con el que empiezan los personajes nuevos (10000 de cobre = 1 de oro)." + }, + "MaxPlayerLevel": { + "t": "Nivel máximo", + "d": "El nivel más alto que puede alcanzar un personaje. El cliente del juego solo admite 80." + }, + "SkipCinematics": { + "t": "Omitir cinemáticas de introducción", + "d": "Si los personajes nuevos ven su película de introducción." + }, + "DurabilityLoss.OnDeath": { + "t": "Durabilidad perdida al morir", + "d": "Porcentaje de durabilidad de los objetos que se pierde al morir." + }, + "Death.SicknessLevel": { + "t": "Enfermedad de resurrección hasta el nivel", + "d": "Los personajes por encima de este nivel sufren la enfermedad de resurrección. -10 la desactiva." + }, + "LeaveGroupOnLogout.Enabled": { + "t": "Dejar el grupo al desconectarse", + "d": "Los jugadores salen de su grupo cuando cierran sesión." + }, + "GM.LoginState": { + "t": "Modo GM al iniciar sesión", + "d": "Si los maestros del juego empiezan con el modo GM activado." + }, + "AllowTwoSide.Accounts": { + "t": "Ambas facciones en una cuenta", + "d": "Una cuenta puede tener personajes de la Alianza y de la Horda." + }, + "AllowTwoSide.Interaction.Chat": { + "t": "Chat entre facciones", + "d": "Los jugadores de la Alianza y de la Horda pueden hablar entre sí." + }, + "AutoBroadcast.On": { + "t": "Anuncios automáticos", + "d": "Difunde a intervalos regulares los mensajes guardados en la base de datos." + }, + "AutoBroadcast.Timer": { + "t": "Intervalo de anuncios", + "d": "Tiempo entre los anuncios automáticos." + }, + "Warden.Enabled": { + "t": "Antitrampas (Warden)", + "d": "Activa la comprobación antitrampas del cliente. Normalmente innecesaria en un servidor privado." + }, + "MapUpdateInterval": { + "t": "Intervalo de actualización de mapas", + "d": "Con qué frecuencia el mundo actualiza los mapas. Más bajo es más fluido, pero usa más CPU." + }, + "MinWorldUpdateTime": { + "t": "Tiempo mínimo de actualización del mundo", + "d": "El menor tiempo entre actualizaciones del mundo. Súbelo para reducir el uso de CPU." + }, + "ThreadPool": { + "t": "Hilos de trabajo", + "d": "Número de hilos de trabajo en segundo plano. Más ayuda con muchos jugadores." + }, + "Network.Threads": { + "t": "Hilos de red", + "d": "Hilos que gestionan las conexiones de los jugadores. Uno basta para servidores pequeños." + }, + "Ra.Enable": { + "t": "Consola remota", + "d": "Permite que el Manager y los scripts envíen comandos al servidor. Solo escucha en este equipo; déjalo así." + }, + "Ra.IP": { + "t": "Dirección de la consola remota", + "d": "Dirección en la que escucha la consola remota. Mantén 127.0.0.1 para que no sea accesible desde internet." + }, + "Updates.EnableDatabases": { + "t": "Actualizaciones automáticas de bases de datos", + "d": "Permite que el servidor cambie él mismo sus bases de datos al arrancar. Déjalo en 0: el Manager aplica y registra las actualizaciones de bases de datos de forma segura." + } + }, + "options": { + "GameType.0": "Normal", + "GameType.1": "Jugador contra jugador", + "GameType.6": "Juego de rol", + "GameType.8": "Juego de rol + JcJ", + "SkipCinematics.0": "Mostrar todas", + "SkipCinematics.1": "Omitir salvo para el primer personaje", + "SkipCinematics.2": "Omitir todas", + "GM.LoginState.0": "Apagado", + "GM.LoginState.1": "Encendido", + "GM.LoginState.2": "Igual que la última vez" + }, + "presets": { + "balanced": { + "t": "Equilibrado", + "d": "La configuración recomendada para el día a día: misiones, relleno de mazmorras y de campos de batalla activados, registros discretos." + }, + "solo-friendly": { + "t": "Apto para jugar solo", + "d": "Bots que te ayudan y completan tus grupos, con una población pequeña y tranquila." + }, + "living-world": { + "t": "Mundo vivo", + "d": "Un mundo más animado: más bots, descansos, desvíos para recolectar y grupos temporales." + }, + "performance": { + "t": "Rendimiento", + "d": "Menos bots y menos cálculo de los bots, para equipos más modestos." + }, + "vanilla": { + "t": "Tasas estándar", + "d": "Todo a velocidad normal (×1)." + }, + "relaxed": { + "t": "Relajado", + "d": "Subida de nivel más rápida y más botín para jugar sin prisa (×2 / ×3)." + }, + "fast": { + "t": "Rápido", + "d": "Progreso rápido para pruebas o sesiones cortas (×5)." + }, + "defaults": { + "t": "Valores recomendados", + "d": "Todos los ajustes vuelven a su valor predeterminado." + } + } +} \ No newline at end of file diff --git a/src/i18n/schema/fr.json b/src/i18n/schema/fr.json new file mode 100644 index 0000000..125bb11 --- /dev/null +++ b/src/i18n/schema/fr.json @@ -0,0 +1,513 @@ +{ + "categories": { + "bots.general": "Général", + "bots.population": "Population", + "bots.login": "Connexion", + "bots.roles": "Rôles", + "bots.openworld": "Monde ouvert", + "bots.quests": "Quêtes", + "bots.combat": "Combat", + "bots.dungeon": "Recherche de donjon", + "bots.battlegrounds": "Champs de bataille", + "bots.social": "Comportement social", + "bots.advanced": "Avancé", + "server.gameplay": "Jeu", + "server.rates": "Taux", + "server.characters": "Personnages", + "server.world": "Monde", + "server.network": "Réseau", + "server.accounts": "Comptes", + "server.logging": "Journaux", + "server.performance": "Performances", + "server.advanced": "Avancé" + }, + "units": { + "ms": "ms", + "%": "%", + "yards": "yards", + "levels": "niveaux", + "x": "×", + "min": "min", + "copper": "cuivre" + }, + "settings": { + "CoaBots.RandomSpawn.DefaultCount": { + "t": "Bots créés par commande", + "d": "Nombre de bots que la commande de création crée quand vous n’indiquez pas de nombre." + }, + "CoaBots.RandomSpawn.MaxCount": { + "t": "Plus grande création en une fois", + "d": "Limite de sécurité pour une commande de création. De très gros lots peuvent figer brièvement le serveur ; n’augmentez donc cette valeur que si personne d’autre ne joue." + }, + "CoaBots.LeveledSpawn.Brackets": { + "t": "Répartition des niveaux des nouveaux bots", + "d": "Comment les nouveaux bots à faire progresser sont répartis par niveau, sous forme de plages pondérées (1-20:40 signifie 40 parts de bots entre les niveaux 1 et 20)." + }, + "CoaBots.RandomSpawn.AutoLogin": { + "t": "Connecter tout de suite les nouveaux bots", + "d": "Les bots tout juste créés se connectent immédiatement au lieu d’attendre dans la base de données." + }, + "CoaBots.RandomSpawn.AccountPrefix": { + "t": "Préfixe des noms de comptes de bots", + "d": "Les bots vivent sur des comptes dont le nom commence par ce préfixe. Le modifier empêche les bots existants de se connecter automatiquement." + }, + "CoaBots.RandomSpawn.BatchSize": { + "t": "Bots créés par étape", + "d": "La création est étalée dans le temps pour garder le serveur fluide. Des valeurs plus élevées sont plus rapides mais peuvent causer des saccades." + }, + "CoaBots.RandomSpawn.BatchIntervalMs": { + "t": "Pause entre les étapes de création", + "d": "Temps entre les étapes de création. Des valeurs plus basses sont plus rapides mais peuvent causer des saccades." + }, + "CoaBots.AutoLoginOnStartup": { + "t": "Connexion automatique des bots", + "d": "Les bots existants se connectent eux-mêmes à chaque démarrage du serveur." + }, + "CoaBots.AutoLogin.MaxCount": { + "t": "Maximum de bots en ligne", + "d": "Le plus grand nombre de bots qui se connectent automatiquement au démarrage." + }, + "CoaBots.AutoLogin.BatchSize": { + "t": "Bots connectés par étape", + "d": "Les connexions sont étalées dans le temps. Des valeurs plus élevées mettent les bots en ligne plus vite mais chargent davantage le serveur." + }, + "CoaBots.AutoLogin.BatchIntervalMs": { + "t": "Pause entre les étapes de connexion", + "d": "Temps entre les étapes de connexion." + }, + "CoaBots.SpecBalance.TankTargetPct": { + "t": "Part visée de tanks", + "d": "Part des bots qui doivent être des tanks." + }, + "CoaBots.SpecBalance.HealerTargetPct": { + "t": "Part visée de soigneurs", + "d": "Part des bots qui doivent être des soigneurs." + }, + "CoaBots.TalentBuildsPath": { + "t": "Fichier de données de talents", + "d": "Emplacement des builds de talents de la communauté. Laissez vide pour utiliser la recherche intégrée." + }, + "CoaBots.World.Enable": { + "t": "Les bots se promènent dans le monde", + "d": "Les bots inactifs font des courses : ils visitent les services de la ville, vont vers des zones de récolte ou de farm, ou se promènent un peu." + }, + "CoaBots.WorldBrain.Enable": { + "t": "IA de quêtes", + "d": "Les bots prennent et accomplissent des quêtes seuls. Désactivée, les bots ne font que récolter, pêcher, farmer et se promener." + }, + "CoaBots.World.ServiceRadius": { + "t": "Rayon de recherche des services de la ville", + "d": "Jusqu’où un bot cherche des marchands et des boîtes aux lettres." + }, + "CoaBots.World.AreaRadius": { + "t": "Rayon de la zone de courses", + "d": "Jusqu’où un bot cherche des zones de récolte ou de farm." + }, + "CoaBots.World.ThinkIntervalMs": { + "t": "Intervalle de vérification des courses", + "d": "Fréquence à laquelle chaque bot reconsidère sa course." + }, + "CoaBots.World.IdleBeforeErrandMs": { + "t": "Inactivité avant une course", + "d": "Durée pendant laquelle un bot ne doit rien trouver à faire avant de commencer une course." + }, + "CoaBots.World.VerboseLog": { + "t": "Journal détaillé des courses", + "d": "Écrit chaque étape des courses dans le journal. Utile pour le débogage, bruyant avec beaucoup de bots." + }, + "CoaBots.Combat.VerboseLog": { + "t": "Journal détaillé des combats", + "d": "Écrit les décisions de combat dans le journal. Très bruyant ; à activer seulement pour traquer un problème précis." + }, + "CoaBots.Profile.IntentMinMs": { + "t": "Activité la plus courte", + "d": "La durée la plus courte pendant laquelle un bot reste sur un même type d’activité." + }, + "CoaBots.Profile.IntentMaxMs": { + "t": "Activité la plus longue", + "d": "La durée la plus longue pendant laquelle un bot reste sur un même type d’activité." + }, + "CoaBots.Grind.SearchRadius": { + "t": "Rayon de recherche pour le farm", + "d": "Jusqu’où un bot cherche des monstres à farmer." + }, + "CoaBots.Grind.MaxLevelAbove": { + "t": "Niveau maximal des monstres à farmer", + "d": "De combien de niveaux au-dessus de lui un bot accepte de combattre en farmant." + }, + "CoaBots.Healer.CriticalHealPct": { + "t": "Seuil de soin d’urgence", + "d": "Les soigneurs passent à leurs soins les plus puissants quand la vie d’un allié tombe sous cette valeur." + }, + "CoaBots.WorldBrain.SearchRadius": { + "t": "Rayon de recherche des cibles", + "d": "Jusqu’où un bot cherche des cibles de quête dans une zone d’objectif." + }, + "CoaBots.WorldBrain.EngageRange": { + "t": "Distance d’engagement", + "d": "Distance à laquelle un bot commence à combattre un monstre de quête." + }, + "CoaBots.WorldBrain.MountDistanceMin": { + "t": "Monter en selle au-delà de (min.)", + "d": "Chaque bot monte pour les trajets plus longs qu’une distance personnelle tirée entre cette valeur et le maximum." + }, + "CoaBots.WorldBrain.MountDistanceMax": { + "t": "Monter en selle au-delà de (max.)", + "d": "Borne supérieure de la distance personnelle de monte." + }, + "CoaBots.WorldBrain.TaxiMinDistance": { + "t": "Utiliser les trajets aériens au-delà de", + "d": "Les trajets plus longs utilisent un trajet aérien quand le bot connaît un itinéraire." + }, + "CoaBots.WorldBrain.SessionBreaks": { + "t": "Faire des pauses", + "d": "Les bots alternent quêtes et quelques minutes de vie en ville, comme un joueur." + }, + "CoaBots.WorldBrain.GatherDetours": { + "t": "Récolter herbes et minerai à proximité", + "d": "Les récolteurs quittent leur chemin pour un filon juste à côté." + }, + "CoaBots.WorldBrain.MaxActiveQuests": { + "t": "Maximum de quêtes actives", + "d": "Nombre de quêtes qu’un bot porte en même temps." + }, + "CoaBots.WorldBrain.AcceptEliteQuests": { + "t": "Accepter les quêtes d’élite", + "d": "Les bots solo prennent des quêtes d’élite. Désactivé par défaut car ils ne peuvent généralement pas les finir seuls." + }, + "CoaBots.WorldBrain.QuestLevelBelow": { + "t": "Quêtes sous son propre niveau", + "d": "De combien de niveaux en dessous de lui un bot accepte encore des quêtes." + }, + "CoaBots.WorldBrain.QuestLevelAbove": { + "t": "Quêtes au-dessus de son propre niveau", + "d": "De combien de niveaux au-dessus de lui un bot accepte encore des quêtes." + }, + "CoaBots.WorldBrain.MaxMobLevelAbove": { + "t": "Niveau maximal des monstres de quête", + "d": "De combien un monstre de quête peut dépasser le niveau du bot." + }, + "CoaBots.WorldBrain.MaxObjectiveDistance": { + "t": "Objectif de quête le plus éloigné", + "d": "Les quêtes dont les objectifs sont plus loin ne sont pas prises." + }, + "CoaBots.WorldBrain.GiverSearchRadius": { + "t": "Rayon de recherche des donneurs de quêtes", + "d": "Jusqu’où un bot cherche des donneurs de quêtes." + }, + "CoaBots.WorldBrain.MaxBadAreasPerObjective": { + "t": "Zones essayées par objectif", + "d": "Nombre de zones qu’un bot abandonne avant de mettre la quête de côté." + }, + "CoaBots.WorldBrain.QuestSuspendMs": { + "t": "Durée de mise de côté (courte)", + "d": "Durée pendant laquelle une quête est mise de côté après l’abandon du bot." + }, + "CoaBots.WorldBrain.QuestSuspendMaxMs": { + "t": "Durée de mise de côté (longue)", + "d": "La durée maximale pendant laquelle une quête peut rester de côté après des échecs répétés." + }, + "CoaBots.LfgFill.Enable": { + "t": "Complétion par bots de la recherche de donjon", + "d": "Quand vous vous inscrivez seul pour un donjon, des bots comblent les rôles manquants de tank, soigneur et dégâts." + }, + "CoaBots.AutoQueueDungeon.Enable": { + "t": "Les bots s’inscrivent seuls aux donjons", + "d": "Expérimental : des bots tanks inactifs s’inscrivent seuls à un donjon et la complétion ci-dessus termine le groupe." + }, + "CoaBots.BGFill.Enable": { + "t": "Complétion par bots des champs de bataille", + "d": "Quand quelqu’un s’inscrit à un champ de bataille, les deux équipes sont complétées par des bots pour que la partie commence tout de suite." + }, + "CoaBots.BGFill.TargetPlayersPerTeam": { + "t": "Taille d’équipe en champ de bataille", + "d": "Nombre de bots par équipe jusqu’auquel compléter. 0 signifie une équipe complète pour ce champ de bataille." + }, + "CoaBots.WorldBrain.HelpOthers": { + "t": "Les bots aident les joueurs proches", + "d": "Un bot de passage rejoint un combat qu’un joueur ami est en train de perdre, sans prendre son butin ni son crédit." + }, + "CoaBots.WorldBrain.HelpRadius": { + "t": "Distance d’aide", + "d": "À quelle distance un bot doit être pour rejoindre un combat." + }, + "CoaBots.WorldBrain.HelpHealthPct": { + "t": "Aider sous une vie de", + "d": "Les bots aident quand la vie du joueur qui combat est inférieure à cette valeur." + }, + "CoaBots.WorldBrain.ResurrectOthers": { + "t": "Les bots ressuscitent les joueurs tombés", + "d": "Les bots qui connaissent un sort de résurrection relèvent les cadavres amis." + }, + "CoaBots.WorldBrain.TemporaryParties": { + "t": "Groupes de bots temporaires", + "d": "Des bots de niveau proche avec la même quête s’unissent brièvement." + }, + "CoaBots.WorldBrain.PartyMaxSize": { + "t": "Taille des groupes temporaires", + "d": "Plus grand groupe temporaire." + }, + "CoaBots.WorldBrain.PartyRadius": { + "t": "Distance de formation de groupe", + "d": "À quelle distance les bots doivent être pour s’unir." + }, + "CoaBots.WorldBrain.PartyMinMinutes": { + "t": "Durée minimale de groupe", + "d": "Durée minimale d’un groupe temporaire." + }, + "CoaBots.WorldBrain.PartyMaxMinutes": { + "t": "Durée maximale de groupe", + "d": "Durée maximale d’un groupe temporaire." + }, + "CoaBots.WorldBrain.PlannerMinMs": { + "t": "Intervalle du planificateur (min.)", + "d": "Temps le plus court entre deux passes de planification d’un bot." + }, + "CoaBots.WorldBrain.PlannerMaxMs": { + "t": "Intervalle du planificateur (max.)", + "d": "Temps le plus long entre deux passes de planification d’un bot." + }, + "CoaBots.WorldBrain.ScanMinMs": { + "t": "Intervalle de recherche de cibles (min.)", + "d": "Temps le plus court entre deux recherches de cibles." + }, + "CoaBots.WorldBrain.ScanMaxMs": { + "t": "Intervalle de recherche de cibles (max.)", + "d": "Temps le plus long entre deux recherches de cibles." + }, + "CoaBots.WorldBrain.SearchTimeoutMs": { + "t": "Limite de temps de recherche de zone", + "d": "Durée pendant laquelle un bot fouille une zone vide avant d’en essayer une autre." + }, + "CoaBots.WorldBrain.ApproachTimeoutMs": { + "t": "Limite de temps d’approche", + "d": "Durée pendant laquelle un bot marche vers une cible réservée." + }, + "CoaBots.WorldBrain.TravelTimeoutMs": { + "t": "Limite de temps de trajet", + "d": "Durée maximale d’un trajet complet vers une zone." + }, + "CoaBots.WorldBrain.Weight.TravelPer100Yards": { + "t": "Poids de préférence : TravelPer100Yards", + "d": "Importance que les bots accordent à ce facteur pour choisir ce qu’ils font ensuite. Ne modifiez que si vous connaissez le planificateur." + }, + "CoaBots.WorldBrain.Weight.CrowdPerBot": { + "t": "Poids de préférence : CrowdPerBot", + "d": "Importance que les bots accordent à ce facteur pour choisir ce qu’ils font ensuite. Ne modifiez que si vous connaissez le planificateur." + }, + "CoaBots.WorldBrain.Weight.Overlap": { + "t": "Poids de préférence : Overlap", + "d": "Importance que les bots accordent à ce facteur pour choisir ce qu’ils font ensuite. Ne modifiez que si vous connaissez le planificateur." + }, + "CoaBots.WorldBrain.Weight.TurnIn": { + "t": "Poids de préférence : TurnIn", + "d": "Importance que les bots accordent à ce facteur pour choisir ce qu’ils font ensuite. Ne modifiez que si vous connaissez le planificateur." + }, + "CoaBots.WorldBrain.Weight.Accept": { + "t": "Poids de préférence : Accept", + "d": "Importance que les bots accordent à ce facteur pour choisir ce qu’ils font ensuite. Ne modifiez que si vous connaissez le planificateur." + }, + "CoaBots.WorldBrain.Weight.AreaOccupancy": { + "t": "Poids de préférence : AreaOccupancy", + "d": "Importance que les bots accordent à ce facteur pour choisir ce qu’ils font ensuite. Ne modifiez que si vous connaissez le planificateur." + }, + "CoaBots.WorldBrain.Weight.TargetReserved": { + "t": "Poids de préférence : TargetReserved", + "d": "Importance que les bots accordent à ce facteur pour choisir ce qu’ils font ensuite. Ne modifiez que si vous connaissez le planificateur." + }, + "Rate.XP.Kill": { + "t": "Expérience des morts", + "d": "Multiplicateur de l’expérience gagnée en tuant des monstres. 1 est normal." + }, + "Rate.XP.Quest": { + "t": "Expérience des quêtes", + "d": "Multiplicateur de l’expérience gagnée avec les quêtes." + }, + "Rate.XP.Quest.DF": { + "t": "Expérience des quêtes quotidiennes / recherche de donjon", + "d": "Multiplicateur de l’expérience des quêtes de la recherche de donjon." + }, + "Rate.XP.Explore": { + "t": "Expérience d’exploration", + "d": "Multiplicateur de l’expérience de la découverte de nouvelles zones." + }, + "Rate.Drop.Item.Normal": { + "t": "Taux de butin d’objets", + "d": "Multiplicateur de la fréquence de chute des objets de qualité normale." + }, + "Rate.Drop.Money": { + "t": "Taux de butin d’or", + "d": "Multiplicateur de l’or laissé par les monstres." + }, + "Rate.Honor": { + "t": "Gain d’honneur", + "d": "Multiplicateur des points d’honneur gagnés." + }, + "Rate.Reputation.Gain": { + "t": "Gain de réputation", + "d": "Multiplicateur de la réputation gagnée." + }, + "Rate.Rest.InGame": { + "t": "Bonus de repos en jeu", + "d": "Vitesse à laquelle l’expérience de repos est consommée pendant que vous jouez." + }, + "Rate.Creature.Normal.Damage": { + "t": "Dégâts des monstres", + "d": "Multiplicateur des dégâts des monstres normaux. Change beaucoup la difficulté." + }, + "Rate.Creature.Normal.HP": { + "t": "Vie des monstres", + "d": "Multiplicateur de la vie des monstres normaux. Change beaucoup la difficulté." + }, + "PlayerLimit": { + "t": "Nombre maximal de joueurs", + "d": "Combien de joueurs peuvent être en ligne en même temps. 0 signifie aucune limite." + }, + "GameType": { + "t": "Type de royaume", + "d": "Le type de royaume affiché dans la liste des royaumes." + }, + "RealmZone": { + "t": "Zone du royaume", + "d": "Le groupe de langue / de région du royaume montré aux clients." + }, + "PlayerSaveInterval": { + "t": "Intervalle de sauvegarde automatique", + "d": "Fréquence de sauvegarde des personnages des joueurs pendant qu’ils sont en ligne." + }, + "CharactersPerAccount": { + "t": "Personnages par compte", + "d": "Nombre maximal de personnages qu’un compte peut avoir sur tous les royaumes." + }, + "CharactersPerRealm": { + "t": "Personnages par royaume", + "d": "Nombre maximal de personnages qu’un compte peut avoir sur ce royaume." + }, + "StartPlayerLevel": { + "t": "Niveau de départ", + "d": "Niveau auquel commencent les nouveaux personnages." + }, + "StartPlayerMoney": { + "t": "Or de départ", + "d": "Cuivre avec lequel commencent les nouveaux personnages (10000 cuivre = 1 or)." + }, + "MaxPlayerLevel": { + "t": "Niveau maximal", + "d": "Niveau le plus élevé qu’un personnage peut atteindre. Le client du jeu ne gère que 80." + }, + "SkipCinematics": { + "t": "Ignorer les cinématiques d’introduction", + "d": "Si les nouveaux personnages voient leur film d’introduction." + }, + "DurabilityLoss.OnDeath": { + "t": "Durabilité perdue à la mort", + "d": "Pourcentage de durabilité des objets perdu à la mort." + }, + "Death.SicknessLevel": { + "t": "Maladie de résurrection jusqu’au niveau", + "d": "Les personnages au-dessus de ce niveau reçoivent la maladie de résurrection. -10 la désactive." + }, + "LeaveGroupOnLogout.Enabled": { + "t": "Quitter le groupe à la déconnexion", + "d": "Les joueurs sont retirés de leur groupe quand ils se déconnectent." + }, + "GM.LoginState": { + "t": "Mode MJ à la connexion", + "d": "Si les maîtres de jeu démarrent avec le mode MJ activé." + }, + "AllowTwoSide.Accounts": { + "t": "Les deux factions sur un compte", + "d": "Un compte peut avoir des personnages de l’Alliance et de la Horde." + }, + "AllowTwoSide.Interaction.Chat": { + "t": "Discussion entre factions", + "d": "Les joueurs de l’Alliance et de la Horde peuvent se parler." + }, + "AutoBroadcast.On": { + "t": "Annonces automatiques", + "d": "Diffuse à intervalles réguliers les messages stockés dans la base de données." + }, + "AutoBroadcast.Timer": { + "t": "Intervalle des annonces", + "d": "Temps entre les annonces automatiques." + }, + "Warden.Enabled": { + "t": "Anti-triche (Warden)", + "d": "Active la vérification anti-triche du client. Généralement inutile sur un serveur privé." + }, + "MapUpdateInterval": { + "t": "Intervalle de mise à jour des cartes", + "d": "Fréquence à laquelle le monde met à jour les cartes. Plus bas est plus fluide mais utilise plus de processeur." + }, + "MinWorldUpdateTime": { + "t": "Temps minimal de mise à jour du monde", + "d": "Temps le plus court entre deux mises à jour du monde. Augmentez-le pour réduire l’utilisation du processeur." + }, + "ThreadPool": { + "t": "Threads de travail", + "d": "Nombre de threads de travail en arrière-plan. Plus aide avec beaucoup de joueurs." + }, + "Network.Threads": { + "t": "Threads réseau", + "d": "Threads qui gèrent les connexions des joueurs. Un seul suffit pour les petits serveurs." + }, + "Ra.Enable": { + "t": "Console distante", + "d": "Permet au Manager et aux scripts d’envoyer des commandes au serveur. Elle n’écoute que cet ordinateur ; laissez-la ainsi." + }, + "Ra.IP": { + "t": "Adresse de la console distante", + "d": "Adresse sur laquelle écoute la console distante. Gardez 127.0.0.1 pour qu’elle ne soit pas accessible depuis Internet." + }, + "Updates.EnableDatabases": { + "t": "Mises à jour automatiques des bases de données", + "d": "Permet au serveur de modifier lui-même ses bases de données au démarrage. Gardez 0 : le Manager applique et suit les mises à jour de base de données en toute sécurité." + } + }, + "options": { + "GameType.0": "Normal", + "GameType.1": "Joueur contre joueur", + "GameType.6": "Jeu de rôle", + "GameType.8": "Jeu de rôle + JcJ", + "SkipCinematics.0": "Tout afficher", + "SkipCinematics.1": "Ignorer sauf pour le premier personnage", + "SkipCinematics.2": "Tout ignorer", + "GM.LoginState.0": "Désactivé", + "GM.LoginState.1": "Activé", + "GM.LoginState.2": "Comme la dernière fois" + }, + "presets": { + "balanced": { + "t": "Équilibré", + "d": "La configuration recommandée au quotidien : quêtes, complétion des donjons et des champs de bataille activées, journaux discrets." + }, + "solo-friendly": { + "t": "Adapté au solo", + "d": "Des bots qui vous aident et complètent vos groupes, avec une petite population tranquille." + }, + "living-world": { + "t": "Monde vivant", + "d": "Un monde plus animé : plus de bots, pauses, détours de récolte et groupes temporaires." + }, + "performance": { + "t": "Performances", + "d": "Moins de bots et moins de réflexion des bots, pour les ordinateurs plus modestes." + }, + "vanilla": { + "t": "Taux standard", + "d": "Tout à vitesse normale (×1)." + }, + "relaxed": { + "t": "Détendu", + "d": "Progression plus rapide et plus de butin pour un jeu décontracté (×2 / ×3)." + }, + "fast": { + "t": "Rapide", + "d": "Progression rapide pour des tests ou de courtes sessions (×5)." + }, + "defaults": { + "t": "Valeurs recommandées", + "d": "Tous les paramètres reviennent à leur valeur par défaut." + } + } +} \ No newline at end of file diff --git a/src/i18n/schema/ru.json b/src/i18n/schema/ru.json new file mode 100644 index 0000000..e602a4b --- /dev/null +++ b/src/i18n/schema/ru.json @@ -0,0 +1,513 @@ +{ + "categories": { + "bots.general": "Общее", + "bots.population": "Население", + "bots.login": "Вход", + "bots.roles": "Роли", + "bots.openworld": "Открытый мир", + "bots.quests": "Задания", + "bots.combat": "Бой", + "bots.dungeon": "Поиск подземелий", + "bots.battlegrounds": "Поля боя", + "bots.social": "Общение и помощь", + "bots.advanced": "Дополнительно", + "server.gameplay": "Игровой процесс", + "server.rates": "Множители", + "server.characters": "Персонажи", + "server.world": "Мир", + "server.network": "Сеть", + "server.accounts": "Учётные записи", + "server.logging": "Журналы", + "server.performance": "Производительность", + "server.advanced": "Дополнительно" + }, + "units": { + "ms": "мс", + "%": "%", + "yards": "ярдов", + "levels": "уровней", + "x": "×", + "min": "мин", + "copper": "меди" + }, + "settings": { + "CoaBots.RandomSpawn.DefaultCount": { + "t": "Ботов за одну команду создания", + "d": "Сколько ботов создаёт команда создания, если вы не указали число." + }, + "CoaBots.RandomSpawn.MaxCount": { + "t": "Наибольшая единовременная партия", + "d": "Ограничение безопасности для одной команды создания. Очень большие партии могут ненадолго подвесить сервер, поэтому повышайте значение, только когда больше никто не играет." + }, + "CoaBots.LeveledSpawn.Brackets": { + "t": "Распределение уровней новых ботов", + "d": "Как новые прокачиваемые боты распределяются по уровням: диапазоны с весами (1-20:40 означает 40 частей ботов с уровнями от 1 до 20)." + }, + "CoaBots.RandomSpawn.AutoLogin": { + "t": "Сразу выводить новых ботов в сеть", + "d": "Только что созданные боты входят в игру сразу, а не ждут в базе данных." + }, + "CoaBots.RandomSpawn.AccountPrefix": { + "t": "Префикс имён учётных записей ботов", + "d": "Боты живут на учётных записях, имена которых начинаются с этого префикса. Если его изменить, существующие боты перестанут входить автоматически." + }, + "CoaBots.RandomSpawn.BatchSize": { + "t": "Ботов за один шаг создания", + "d": "Создание растягивается во времени, чтобы сервер работал плавно. Большие значения быстрее, но могут вызывать подвисания." + }, + "CoaBots.RandomSpawn.BatchIntervalMs": { + "t": "Пауза между шагами создания", + "d": "Время между шагами создания. Меньшие значения быстрее, но могут вызывать подвисания." + }, + "CoaBots.AutoLoginOnStartup": { + "t": "Автоматический вход ботов", + "d": "Существующие боты сами входят в игру при каждом запуске сервера." + }, + "CoaBots.AutoLogin.MaxCount": { + "t": "Максимум ботов в сети", + "d": "Наибольшее число ботов, входящих автоматически при запуске." + }, + "CoaBots.AutoLogin.BatchSize": { + "t": "Ботов за один шаг входа", + "d": "Входы растягиваются во времени. Большие значения быстрее выводят ботов в сеть, но сильнее нагружают сервер." + }, + "CoaBots.AutoLogin.BatchIntervalMs": { + "t": "Пауза между шагами входа", + "d": "Время между шагами входа." + }, + "CoaBots.SpecBalance.TankTargetPct": { + "t": "Целевая доля танков", + "d": "Какая доля ботов должна быть танками." + }, + "CoaBots.SpecBalance.HealerTargetPct": { + "t": "Целевая доля целителей", + "d": "Какая доля ботов должна быть целителями." + }, + "CoaBots.TalentBuildsPath": { + "t": "Файл с данными талантов", + "d": "Где хранятся билды талантов от сообщества. Оставьте пустым, чтобы использовать встроенный поиск." + }, + "CoaBots.World.Enable": { + "t": "Боты бродят по миру", + "d": "Бездействующие боты занимаются делами: посещают городские службы, отправляются в места сбора ресурсов или гринда либо немного бродят." + }, + "CoaBots.WorldBrain.Enable": { + "t": "ИИ заданий", + "d": "Боты сами берут и выполняют задания. Если выключить, боты только собирают ресурсы, ловят рыбу, гриндят и бродят." + }, + "CoaBots.World.ServiceRadius": { + "t": "Радиус поиска городских служб", + "d": "Как далеко бот ищет торговцев и почтовые ящики." + }, + "CoaBots.World.AreaRadius": { + "t": "Радиус области дел", + "d": "Как далеко бот ищет места для сбора ресурсов или гринда." + }, + "CoaBots.World.ThinkIntervalMs": { + "t": "Интервал выбора дела", + "d": "Как часто каждый бот пересматривает своё дело." + }, + "CoaBots.World.IdleBeforeErrandMs": { + "t": "Простой до начала дела", + "d": "Сколько времени бот должен не находить себе занятия, прежде чем начнёт дело." + }, + "CoaBots.World.VerboseLog": { + "t": "Подробный журнал дел", + "d": "Записывает в журнал каждый шаг дел. Полезно для отладки, но при большом числе ботов создаёт много шума." + }, + "CoaBots.Combat.VerboseLog": { + "t": "Подробный журнал боя", + "d": "Записывает в журнал решения в бою. Очень шумно; включайте только при поиске конкретной проблемы." + }, + "CoaBots.Profile.IntentMinMs": { + "t": "Кратчайшее занятие", + "d": "Наименьшее время, в течение которого бот держится одного вида занятий." + }, + "CoaBots.Profile.IntentMaxMs": { + "t": "Самое длинное занятие", + "d": "Наибольшее время, в течение которого бот держится одного вида занятий." + }, + "CoaBots.Grind.SearchRadius": { + "t": "Радиус поиска для гринда", + "d": "Как далеко бот ищет монстров для гринда." + }, + "CoaBots.Grind.MaxLevelAbove": { + "t": "Наибольший уровень монстра для гринда", + "d": "На сколько уровней выше себя бот согласен сражаться при гринде." + }, + "CoaBots.Healer.CriticalHealPct": { + "t": "Порог экстренного лечения", + "d": "Целители переключаются на самые сильные исцеления, когда здоровье союзника падает ниже этого значения." + }, + "CoaBots.WorldBrain.SearchRadius": { + "t": "Радиус поиска целей", + "d": "Как далеко бот высматривает цели заданий внутри области задачи." + }, + "CoaBots.WorldBrain.EngageRange": { + "t": "Дистанция начала боя", + "d": "Расстояние, на котором бот начинает бой с монстром из задания." + }, + "CoaBots.WorldBrain.MountDistanceMin": { + "t": "Садиться на транспорт при пути от (мин.)", + "d": "Каждый бот садится на ездовое животное в поездках длиннее личного расстояния, выбираемого между этим значением и максимумом." + }, + "CoaBots.WorldBrain.MountDistanceMax": { + "t": "Садиться на транспорт при пути от (макс.)", + "d": "Верхняя граница личного расстояния для посадки на ездовое животное." + }, + "CoaBots.WorldBrain.TaxiMinDistance": { + "t": "Летать по маршрутам при пути от", + "d": "Поездки длиннее этого значения выполняются на маршрутах перелёта, если бот знает подходящий." + }, + "CoaBots.WorldBrain.SessionBreaks": { + "t": "Делать перерывы", + "d": "Боты чередуют задания с несколькими минутами городской жизни, как игрок." + }, + "CoaBots.WorldBrain.GatherDetours": { + "t": "Собирать травы и руду поблизости", + "d": "Собиратели сходят с пути ради ресурса, лежащего совсем рядом." + }, + "CoaBots.WorldBrain.MaxActiveQuests": { + "t": "Максимум активных заданий", + "d": "Сколько заданий бот несёт одновременно." + }, + "CoaBots.WorldBrain.AcceptEliteQuests": { + "t": "Брать элитные задания", + "d": "Одиночные боты берутся за элитные задания. По умолчанию выключено, так как в одиночку они обычно их не выполняют." + }, + "CoaBots.WorldBrain.QuestLevelBelow": { + "t": "Задания ниже своего уровня", + "d": "На сколько уровней ниже себя бот всё ещё берёт задания." + }, + "CoaBots.WorldBrain.QuestLevelAbove": { + "t": "Задания выше своего уровня", + "d": "На сколько уровней выше себя бот всё ещё берёт задания." + }, + "CoaBots.WorldBrain.MaxMobLevelAbove": { + "t": "Наибольший уровень монстра задания", + "d": "Насколько выше уровня бота может быть монстр из задания." + }, + "CoaBots.WorldBrain.MaxObjectiveDistance": { + "t": "Самая далёкая цель задания", + "d": "Задания, цели которых дальше этого расстояния, не берутся." + }, + "CoaBots.WorldBrain.GiverSearchRadius": { + "t": "Радиус поиска раздающих задания", + "d": "Как далеко бот ищет тех, кто раздаёт задания." + }, + "CoaBots.WorldBrain.MaxBadAreasPerObjective": { + "t": "Областей на одну цель", + "d": "От скольких областей бот отказывается, прежде чем отложить задание." + }, + "CoaBots.WorldBrain.QuestSuspendMs": { + "t": "Время откладывания (короткое)", + "d": "Как долго задание откладывается после того, как бот от него отказался." + }, + "CoaBots.WorldBrain.QuestSuspendMaxMs": { + "t": "Время откладывания (длинное)", + "d": "Наибольший срок, на который задание можно отложить после повторных неудач." + }, + "CoaBots.LfgFill.Enable": { + "t": "Дополнение группы ботами в Поиске подземелий", + "d": "Если вы встаёте в очередь в подземелье в одиночку, боты занимают недостающие роли танка, целителя и бойцов урона." + }, + "CoaBots.AutoQueueDungeon.Enable": { + "t": "Боты сами встают в очередь в подземелья", + "d": "Экспериментально: бездействующие боты-танки сами встают в очередь в подземелье, а дополнение выше собирает группу." + }, + "CoaBots.BGFill.Enable": { + "t": "Дополнение поля боя ботами", + "d": "Когда кто-то встаёт в очередь на поле боя, обе команды пополняются ботами, чтобы матч начался сразу." + }, + "CoaBots.BGFill.TargetPlayersPerTeam": { + "t": "Размер команды на поле боя", + "d": "Сколько ботов в команде добавлять. 0 означает полную команду для этого поля боя." + }, + "CoaBots.WorldBrain.HelpOthers": { + "t": "Боты помогают игрокам поблизости", + "d": "Проходящий мимо бот вступает в бой, который проигрывает дружественный игрок, не забирая его добычу и не претендуя на зачёт." + }, + "CoaBots.WorldBrain.HelpRadius": { + "t": "Дистанция помощи", + "d": "Как близко бот должен находиться, чтобы вступить в бой." + }, + "CoaBots.WorldBrain.HelpHealthPct": { + "t": "Помогать при здоровье ниже", + "d": "Боты помогают, когда здоровье сражающегося игрока ниже этого значения." + }, + "CoaBots.WorldBrain.ResurrectOthers": { + "t": "Боты воскрешают павших игроков", + "d": "Боты, знающие заклинание воскрешения, поднимают дружественные тела." + }, + "CoaBots.WorldBrain.TemporaryParties": { + "t": "Временные группы ботов", + "d": "Боты близкого уровня с одинаковым заданием ненадолго объединяются." + }, + "CoaBots.WorldBrain.PartyMaxSize": { + "t": "Размер временной группы", + "d": "Наибольший размер временной группы." + }, + "CoaBots.WorldBrain.PartyRadius": { + "t": "Расстояние для создания группы", + "d": "Как близко должны быть боты, чтобы объединиться." + }, + "CoaBots.WorldBrain.PartyMinMinutes": { + "t": "Кратчайшее время группы", + "d": "Минимальная длительность временной группы." + }, + "CoaBots.WorldBrain.PartyMaxMinutes": { + "t": "Наибольшее время группы", + "d": "Максимальная длительность временной группы." + }, + "CoaBots.WorldBrain.PlannerMinMs": { + "t": "Интервал планировщика (мин.)", + "d": "Кратчайшее время между проходами планирования бота." + }, + "CoaBots.WorldBrain.PlannerMaxMs": { + "t": "Интервал планировщика (макс.)", + "d": "Наибольшее время между проходами планирования бота." + }, + "CoaBots.WorldBrain.ScanMinMs": { + "t": "Интервал поиска целей (мин.)", + "d": "Кратчайшее время между поисками целей." + }, + "CoaBots.WorldBrain.ScanMaxMs": { + "t": "Интервал поиска целей (макс.)", + "d": "Наибольшее время между поисками целей." + }, + "CoaBots.WorldBrain.SearchTimeoutMs": { + "t": "Лимит времени поиска в области", + "d": "Как долго бот обыскивает пустую область, прежде чем попробовать другую." + }, + "CoaBots.WorldBrain.ApproachTimeoutMs": { + "t": "Лимит времени подхода", + "d": "Как долго бот идёт к выбранной цели." + }, + "CoaBots.WorldBrain.TravelTimeoutMs": { + "t": "Лимит времени пути", + "d": "Сколько может занять вся поездка в область." + }, + "CoaBots.WorldBrain.Weight.TravelPer100Yards": { + "t": "Вес предпочтения: TravelPer100Yards", + "d": "Насколько сильно боты учитывают этот фактор при выборе следующего дела. Меняйте, только если разбираетесь в планировщике." + }, + "CoaBots.WorldBrain.Weight.CrowdPerBot": { + "t": "Вес предпочтения: CrowdPerBot", + "d": "Насколько сильно боты учитывают этот фактор при выборе следующего дела. Меняйте, только если разбираетесь в планировщике." + }, + "CoaBots.WorldBrain.Weight.Overlap": { + "t": "Вес предпочтения: Overlap", + "d": "Насколько сильно боты учитывают этот фактор при выборе следующего дела. Меняйте, только если разбираетесь в планировщике." + }, + "CoaBots.WorldBrain.Weight.TurnIn": { + "t": "Вес предпочтения: TurnIn", + "d": "Насколько сильно боты учитывают этот фактор при выборе следующего дела. Меняйте, только если разбираетесь в планировщике." + }, + "CoaBots.WorldBrain.Weight.Accept": { + "t": "Вес предпочтения: Accept", + "d": "Насколько сильно боты учитывают этот фактор при выборе следующего дела. Меняйте, только если разбираетесь в планировщике." + }, + "CoaBots.WorldBrain.Weight.AreaOccupancy": { + "t": "Вес предпочтения: AreaOccupancy", + "d": "Насколько сильно боты учитывают этот фактор при выборе следующего дела. Меняйте, только если разбираетесь в планировщике." + }, + "CoaBots.WorldBrain.Weight.TargetReserved": { + "t": "Вес предпочтения: TargetReserved", + "d": "Насколько сильно боты учитывают этот фактор при выборе следующего дела. Меняйте, только если разбираетесь в планировщике." + }, + "Rate.XP.Kill": { + "t": "Опыт за убийства", + "d": "Множитель опыта за убийство монстров. 1 — обычное значение." + }, + "Rate.XP.Quest": { + "t": "Опыт за задания", + "d": "Множитель опыта за задания." + }, + "Rate.XP.Quest.DF": { + "t": "Опыт за ежедневные задания и Поиск подземелий", + "d": "Множитель опыта за задания Поиска подземелий." + }, + "Rate.XP.Explore": { + "t": "Опыт за исследование", + "d": "Множитель опыта за открытие новых областей." + }, + "Rate.Drop.Item.Normal": { + "t": "Шанс выпадения предметов", + "d": "Множитель частоты выпадения предметов обычного качества." + }, + "Rate.Drop.Money": { + "t": "Шанс выпадения золота", + "d": "Множитель золота, выпадающего с монстров." + }, + "Rate.Honor": { + "t": "Получение чести", + "d": "Множитель получаемых очков чести." + }, + "Rate.Reputation.Gain": { + "t": "Получение репутации", + "d": "Множитель получаемой репутации." + }, + "Rate.Rest.InGame": { + "t": "Бонус отдыха во время игры", + "d": "Скорость, с которой расходуется накопленный отдых во время игры." + }, + "Rate.Creature.Normal.Damage": { + "t": "Урон монстров", + "d": "Множитель урона обычных монстров. Сильно меняет сложность." + }, + "Rate.Creature.Normal.HP": { + "t": "Здоровье монстров", + "d": "Множитель здоровья обычных монстров. Сильно меняет сложность." + }, + "PlayerLimit": { + "t": "Максимум игроков", + "d": "Сколько игроков может быть в сети одновременно. 0 означает без ограничений." + }, + "GameType": { + "t": "Тип мира", + "d": "Тип мира, отображаемый в списке миров." + }, + "RealmZone": { + "t": "Зона мира", + "d": "Языковая или региональная группа мира, показываемая клиентам." + }, + "PlayerSaveInterval": { + "t": "Интервал автосохранения", + "d": "Как часто персонажи игроков сохраняются, пока они в сети." + }, + "CharactersPerAccount": { + "t": "Персонажей на учётную запись", + "d": "Наибольшее число персонажей на учётной записи во всех мирах." + }, + "CharactersPerRealm": { + "t": "Персонажей в мире", + "d": "Наибольшее число персонажей одной учётной записи в этом мире." + }, + "StartPlayerLevel": { + "t": "Начальный уровень", + "d": "Уровень, с которого начинают новые персонажи." + }, + "StartPlayerMoney": { + "t": "Начальное золото", + "d": "Сколько меди получают новые персонажи (10000 меди = 1 золото)." + }, + "MaxPlayerLevel": { + "t": "Максимальный уровень", + "d": "Наивысший уровень, которого может достичь персонаж. Клиент игры поддерживает только 80." + }, + "SkipCinematics": { + "t": "Пропуск вступительных роликов", + "d": "Показывать ли новым персонажам вступительный ролик." + }, + "DurabilityLoss.OnDeath": { + "t": "Потеря прочности при смерти", + "d": "Процент прочности предметов, теряемый при смерти." + }, + "Death.SicknessLevel": { + "t": "Болезнь воскрешения до уровня", + "d": "Персонажи выше этого уровня получают болезнь воскрешения. Значение -10 отключает её." + }, + "LeaveGroupOnLogout.Enabled": { + "t": "Покидать группу при выходе", + "d": "Игроки исключаются из группы, когда выходят из игры." + }, + "GM.LoginState": { + "t": "Режим ГМ при входе", + "d": "Включён ли режим ГМ у игровых мастеров при входе." + }, + "AllowTwoSide.Accounts": { + "t": "Обе фракции на одной учётной записи", + "d": "На одной учётной записи можно иметь персонажей Альянса и Орды." + }, + "AllowTwoSide.Interaction.Chat": { + "t": "Общий чат фракций", + "d": "Игроки Альянса и Орды могут общаться друг с другом." + }, + "AutoBroadcast.On": { + "t": "Автоматические объявления", + "d": "Регулярно рассылать сообщения, хранящиеся в базе данных." + }, + "AutoBroadcast.Timer": { + "t": "Интервал объявлений", + "d": "Время между автоматическими объявлениями." + }, + "Warden.Enabled": { + "t": "Античит (Warden)", + "d": "Включает проверку античита на стороне клиента. На частном сервере обычно не нужна." + }, + "MapUpdateInterval": { + "t": "Интервал обновления карт", + "d": "Как часто мир обновляет карты. Меньше — плавнее, но больше нагрузка на процессор." + }, + "MinWorldUpdateTime": { + "t": "Минимальное время обновления мира", + "d": "Наименьшее время между обновлениями мира. Увеличьте, чтобы снизить нагрузку на процессор." + }, + "ThreadPool": { + "t": "Рабочие потоки", + "d": "Число фоновых рабочих потоков. Больше помогает при большом числе игроков." + }, + "Network.Threads": { + "t": "Сетевые потоки", + "d": "Потоки, обрабатывающие подключения игроков. Для небольших серверов хватает одного." + }, + "Ra.Enable": { + "t": "Удалённая консоль", + "d": "Позволяет менеджеру и скриптам отправлять серверу команды. Она слушает только этот компьютер; оставьте так." + }, + "Ra.IP": { + "t": "Адрес удалённой консоли", + "d": "Адрес, на котором слушает удалённая консоль. Оставьте 127.0.0.1, чтобы она не была доступна из интернета." + }, + "Updates.EnableDatabases": { + "t": "Автоматические обновления баз данных", + "d": "Позволяет серверу самому менять свои базы данных при запуске. Оставьте 0: менеджер безопасно применяет и учитывает обновления баз данных." + } + }, + "options": { + "GameType.0": "Обычный", + "GameType.1": "PvP", + "GameType.6": "Ролевой", + "GameType.8": "Ролевой + PvP", + "SkipCinematics.0": "Показывать все", + "SkipCinematics.1": "Пропускать для всех, кроме первого персонажа", + "SkipCinematics.2": "Пропускать все", + "GM.LoginState.0": "Выключен", + "GM.LoginState.1": "Включён", + "GM.LoginState.2": "Как в прошлый раз" + }, + "presets": { + "balanced": { + "t": "Сбалансированный", + "d": "Рекомендуемая повседневная настройка: задания, дополнение групп в подземельях и на полях боя включены, журналы тихие." + }, + "solo-friendly": { + "t": "Для одиночной игры", + "d": "Боты, которые помогают вам и дополняют ваши группы, небольшое спокойное население." + }, + "living-world": { + "t": "Живой мир", + "d": "Более оживлённый мир: больше ботов, перерывы, отклонения ради сбора ресурсов и временные группы." + }, + "performance": { + "t": "Производительность", + "d": "Меньше ботов и меньше вычислений на ботов — для слабых компьютеров." + }, + "vanilla": { + "t": "Стандартные множители", + "d": "Всё на обычной скорости (×1)." + }, + "relaxed": { + "t": "Спокойный", + "d": "Быстрая прокачка и больше добычи для неспешной игры (×2 / ×3)." + }, + "fast": { + "t": "Быстрый", + "d": "Быстрое развитие для тестов или коротких сессий (×5)." + }, + "defaults": { + "t": "Рекомендуемые значения", + "d": "Все настройки возвращаются к значениям по умолчанию." + } + } +} \ No newline at end of file diff --git a/src/screens/CompanionsCard.tsx b/src/screens/CompanionsCard.tsx index 9715b62..4e68dc7 100644 --- a/src/screens/CompanionsCard.tsx +++ b/src/screens/CompanionsCard.tsx @@ -3,7 +3,7 @@ import { Loader2 } from "lucide-react"; import { api, asUiError, type CompanionSizes, type Population, type UiError } from "@/lib/api"; import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; -import { useHuman, useT } from "@/i18n"; +import { hasKey, useHuman, useT, type Key } from "@/i18n"; export function CompanionsCard({ serverId }: { serverId: string }) { const t = useT(); @@ -35,8 +35,15 @@ export function CompanionsCard({ serverId }: { serverId: string }) { }; }, [serverId]); + // The backend describes a size's warning in English; show the translated text for the two known kinds. + const warningFor = (size?: { bots: number; warning: string | null }) => { + if (!size?.warning) return null; + return size.warning.startsWith(`${size.bots} companions`) + ? t("comp.warnHardware", { n: size.bots, cores: sizes?.hardware.cores ?? "?", ram: sizes ? sizes.hardware.ram_gb.toFixed(0) : "?" }) + : t("comp.warnMemory"); + }; const count = choice === "custom" ? Number(custom) : (sizes?.sizes.find((s) => s.id === choice)?.bots ?? 0); - const warning = choice === "custom" ? (count > 500 ? t("comp.largeWarning") : null) : (sizes?.sizes.find((s) => s.id === choice)?.warning ?? null); + const warning = choice === "custom" ? (count > 500 ? t("comp.largeWarning") : null) : (warningFor(sizes?.sizes.find((s) => s.id === choice))); const valid = Number.isInteger(count) && count >= 1 && count <= 2000; async function add() { @@ -70,7 +77,7 @@ export function CompanionsCard({ serverId }: { serverId: string }) { {sizes?.sizes.map((s) => ( ))}