find_sln locates a .sln in the working folder; build_sln locates MSBuild via vswhere and builds the solution's default config (compiles the UE game module for Unreal projects), streaming output as build-log events. A build overlay shows the live log with error/warning coloring and a status. Wired into Tools (Ctrl+B) and the Working-folder right-click menu when a .sln is found. New strings translated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
267 lines
35 KiB
TypeScript
267 lines
35 KiB
TypeScript
// Lightweight i18n. English strings are the keys; translations live per-language.
|
||
// t() reads the module-level LANG, so any component re-rendered after a language
|
||
// change (the whole tree re-renders from App) picks up the new language.
|
||
|
||
export type Lang = "en" | "ru" | "de" | "fr" | "es";
|
||
|
||
export const LANGS: { code: Lang; name: string; flag: string }[] = [
|
||
{ code: "en", name: "English", flag: "🇬🇧" },
|
||
{ code: "ru", name: "Русский", flag: "🇷🇺" },
|
||
{ code: "de", name: "Deutsch", flag: "🇩🇪" },
|
||
{ code: "fr", name: "Français", flag: "🇫🇷" },
|
||
{ code: "es", name: "Español", flag: "🇪🇸" },
|
||
];
|
||
|
||
function load(): Lang {
|
||
try { const l = localStorage.getItem("exd-lang") as Lang; return LANGS.some((x) => x.code === l) ? l : "en"; }
|
||
catch { return "en"; }
|
||
}
|
||
export let LANG: Lang = load();
|
||
export function setLangGlobal(l: Lang) { LANG = l; try { localStorage.setItem("exd-lang", l); } catch {} }
|
||
|
||
type Tr = Partial<Record<Lang, string>>;
|
||
const D: Record<string, Tr> = {
|
||
// window controls
|
||
"Minimize": { ru: "Свернуть", de: "Minimieren", fr: "Réduire", es: "Minimizar" },
|
||
"Maximize": { ru: "Развернуть", de: "Maximieren", fr: "Agrandir", es: "Maximizar" },
|
||
"Close": { ru: "Закрыть", de: "Schließen", fr: "Fermer", es: "Cerrar" },
|
||
"Theme": { ru: "Тема", de: "Thema", fr: "Thème", es: "Tema" },
|
||
"Restoring session…": { ru: "Восстановление сессии…", de: "Sitzung wird wiederhergestellt…", fr: "Restauration de la session…", es: "Restaurando sesión…" },
|
||
// startup splash
|
||
"Connecting to server…": { ru: "Подключение к серверу…", de: "Verbinde mit Server…", fr: "Connexion au serveur…", es: "Conectando al servidor…" },
|
||
"Authenticating…": { ru: "Авторизация…", de: "Authentifizierung…", fr: "Authentification…", es: "Autenticando…" },
|
||
"Loading workspace…": { ru: "Загрузка workspace…", de: "Workspace wird geladen…", fr: "Chargement du workspace…", es: "Cargando workspace…" },
|
||
"Syncing state…": { ru: "Синхронизация…", de: "Zustand wird synchronisiert…", fr: "Synchronisation…", es: "Sincronizando…" },
|
||
// server transfer dialog
|
||
"Submitting to server": { ru: "Отправка на сервер", de: "Wird an Server gesendet", fr: "Envoi au serveur", es: "Enviando al servidor" },
|
||
"Getting latest from server": { ru: "Загрузка с сервера", de: "Neueste Version wird geladen", fr: "Récupération depuis le serveur", es: "Obteniendo del servidor" },
|
||
"{n} files": { ru: "{n} файлов", de: "{n} Dateien", fr: "{n} fichiers", es: "{n} archivos" },
|
||
"Uploading…": { ru: "Отправка…", de: "Wird hochgeladen…", fr: "Envoi…", es: "Subiendo…" },
|
||
"Downloading…": { ru: "Скачивание…", de: "Wird heruntergeladen…", fr: "Téléchargement…", es: "Descargando…" },
|
||
|
||
// connect screen
|
||
"Connect to Perforce": { ru: "Подключение к Perforce", de: "Mit Perforce verbinden", fr: "Se connecter à Perforce", es: "Conectar a Perforce" },
|
||
"Exbyte Depot — sign in to your P4 server": { ru: "Exbyte Depot — вход на ваш сервер P4", de: "Exbyte Depot — bei deinem P4-Server anmelden", fr: "Exbyte Depot — connectez-vous à votre serveur P4", es: "Exbyte Depot — inicia sesión en tu servidor P4" },
|
||
"Server": { ru: "Сервер", de: "Server", fr: "Serveur", es: "Servidor" },
|
||
"User": { ru: "Пользователь", de: "Benutzer", fr: "Utilisateur", es: "Usuario" },
|
||
"Password": { ru: "Пароль", de: "Passwort", fr: "Mot de passe", es: "Contraseña" },
|
||
"Workspace": { ru: "Workspace", de: "Workspace", fr: "Workspace", es: "Workspace" },
|
||
"workspace name (not a folder path!)": { ru: "имя workspace (не путь к папке!)", de: "Workspace-Name (kein Ordnerpfad!)", fr: "nom du workspace (pas un chemin !)", es: "nombre del workspace (¡no una ruta!)" },
|
||
"Connecting…": { ru: "Подключение…", de: "Verbinde…", fr: "Connexion…", es: "Conectando…" },
|
||
"Connect": { ru: "Подключиться", de: "Verbinden", fr: "Se connecter", es: "Conectar" },
|
||
|
||
// toolbar
|
||
"Switch workspace · right-click for more": { ru: "Сменить workspace · ПКМ — ещё", de: "Workspace wechseln · Rechtsklick für mehr", fr: "Changer de workspace · clic droit pour plus", es: "Cambiar workspace · clic derecho para más" },
|
||
"Choose the project working folder · right-click for more": { ru: "Выбрать рабочую папку проекта · ПКМ — ещё", de: "Projekt-Arbeitsordner wählen · Rechtsklick für mehr", fr: "Choisir le dossier de travail · clic droit pour plus", es: "Elegir carpeta de trabajo · clic derecho para más" },
|
||
"Open in Explorer": { ru: "Открыть в проводнике", de: "Im Explorer öffnen", fr: "Ouvrir dans l’explorateur", es: "Abrir en el explorador" },
|
||
"Switch workspace…": { ru: "Сменить workspace…", de: "Workspace wechseln…", fr: "Changer de workspace…", es: "Cambiar workspace…" },
|
||
"Copy name": { ru: "Скопировать имя", de: "Namen kopieren", fr: "Copier le nom", es: "Copiar nombre" },
|
||
"Choose another folder…": { ru: "Выбрать другую папку…", de: "Anderen Ordner wählen…", fr: "Choisir un autre dossier…", es: "Elegir otra carpeta…" },
|
||
"Copy path": { ru: "Скопировать путь", de: "Pfad kopieren", fr: "Copier le chemin", es: "Copiar ruta" },
|
||
"Working folder": { ru: "Рабочая папка", de: "Arbeitsordner", fr: "Dossier de travail", es: "Carpeta de trabajo" },
|
||
"whole workspace (//…)": { ru: "весь workspace (//…)", de: "gesamter Workspace (//…)", fr: "workspace entier (//…)", es: "todo el workspace (//…)" },
|
||
"Drag to resize": { ru: "Тянуть — изменить ширину", de: "Ziehen zum Anpassen", fr: "Glisser pour redimensionner", es: "Arrastra para redimensionar" },
|
||
"Submit committed to the server (push)": { ru: "Отправить закоммиченное на сервер (push)", de: "Committed an Server senden (push)", fr: "Envoyer les commits au serveur (push)", es: "Enviar lo confirmado al servidor (push)" },
|
||
"Submit to server": { ru: "Submit на сервер", de: "An Server senden", fr: "Envoyer au serveur", es: "Enviar al servidor" },
|
||
"{n} changelist(s) → push": { ru: "{n} changelist(ов) → push", de: "{n} Changelist(s) → push", fr: "{n} changelist(s) → push", es: "{n} changelist(s) → push" },
|
||
"Get Latest": { ru: "Get Latest", de: "Get Latest", fr: "Get Latest", es: "Get Latest" },
|
||
"Working…": { ru: "Работаю…", de: "Arbeite…", fr: "En cours…", es: "Trabajando…" },
|
||
"pull from server": { ru: "забрать с сервера (pull)", de: "vom Server holen (pull)", fr: "récupérer du serveur (pull)", es: "traer del servidor (pull)" },
|
||
"Launch": { ru: "Запустить", de: "Starten", fr: "Lancer", es: "Iniciar" },
|
||
"Launch Unreal Engine": { ru: "Запустить Unreal Engine", de: "Unreal Engine starten", fr: "Lancer Unreal Engine", es: "Iniciar Unreal Engine" },
|
||
"Build Solution (.sln)": { ru: "Собрать решение (.sln)", de: "Projektmappe bauen (.sln)", fr: "Compiler la solution (.sln)", es: "Compilar solución (.sln)" },
|
||
"Build Solution — no .sln": { ru: "Собрать решение — нет .sln", de: "Projektmappe bauen — keine .sln", fr: "Compiler — aucune .sln", es: "Compilar — sin .sln" },
|
||
"No .sln found in the working folder. Choose the project folder first.": { ru: "В рабочей папке нет .sln. Сначала выбери папку проекта.", de: "Keine .sln im Arbeitsordner. Wähle zuerst den Projektordner.", fr: "Aucune .sln dans le dossier de travail. Choisissez d’abord le dossier du projet.", es: "No hay .sln en la carpeta de trabajo. Elige primero la carpeta del proyecto." },
|
||
"Build": { ru: "Сборка", de: "Build", fr: "Compilation", es: "Compilación" },
|
||
"Building…": { ru: "Сборка…", de: "Wird gebaut…", fr: "Compilation…", es: "Compilando…" },
|
||
"Build succeeded": { ru: "Сборка успешна", de: "Build erfolgreich", fr: "Compilation réussie", es: "Compilación correcta" },
|
||
"Build failed": { ru: "Сборка провалена", de: "Build fehlgeschlagen", fr: "Échec de la compilation", es: "Compilación fallida" },
|
||
"Starting MSBuild…": { ru: "Запуск MSBuild…", de: "MSBuild wird gestartet…", fr: "Démarrage de MSBuild…", es: "Iniciando MSBuild…" },
|
||
"Open this project in Unreal Engine": { ru: "Открыть проект в Unreal Engine", de: "Projekt in Unreal Engine öffnen", fr: "Ouvrir le projet dans Unreal Engine", es: "Abrir el proyecto en Unreal Engine" },
|
||
"Launching Unreal…": { ru: "Запуск Unreal…", de: "Unreal wird gestartet…", fr: "Lancement d’Unreal…", es: "Iniciando Unreal…" },
|
||
|
||
// tabs / list
|
||
"Changes": { ru: "Changes", de: "Änderungen", fr: "Modifications", es: "Cambios" },
|
||
"History": { ru: "History", de: "Verlauf", fr: "Historique", es: "Historial" },
|
||
"Filter {n} files…": { ru: "Фильтр {n} файлов…", de: "{n} Dateien filtern…", fr: "Filtrer {n} fichiers…", es: "Filtrar {n} archivos…" },
|
||
"{n} changelist(s) committed — ready to Submit": { ru: "{n} changelist(ов) закоммичено — готово к Submit", de: "{n} Changelist(s) committed — bereit zum Submit", fr: "{n} changelist(s) validés — prêts à envoyer", es: "{n} changelist(s) confirmados — listos para enviar" },
|
||
"Scanning disk for changes…": { ru: "Ищу изменения на диске…", de: "Suche Änderungen auf der Festplatte…", fr: "Recherche de modifications sur le disque…", es: "Buscando cambios en el disco…" },
|
||
" for the whole workspace this is slow — pick a project folder above": { ru: " для всего workspace это долго — выбери рабочую папку проекта сверху", de: " für den ganzen Workspace ist das langsam — wähle oben einen Projektordner", fr: " pour tout le workspace c’est lent — choisissez un dossier de projet en haut", es: " para todo el workspace es lento — elige una carpeta de proyecto arriba" },
|
||
"{a} of {b} selected": { ru: "{a} из {b} выбрано", de: "{a} von {b} ausgewählt", fr: "{a} sur {b} sélectionnés", es: "{a} de {b} seleccionados" },
|
||
"Select all": { ru: "Выделить все", de: "Alle auswählen", fr: "Tout sélectionner", es: "Seleccionar todo" },
|
||
"Deselect all": { ru: "Снять выделение", de: "Auswahl aufheben", fr: "Tout désélectionner", es: "Deseleccionar todo" },
|
||
"Refresh": { ru: "Обновить", de: "Aktualisieren", fr: "Rafraîchir", es: "Actualizar" },
|
||
"Scanning…": { ru: "Сканирую…", de: "Scanne…", fr: "Analyse…", es: "Analizando…" },
|
||
"Re-read open files (p4 opened)": { ru: "Перечитать открытые файлы (p4 opened)", de: "Offene Dateien neu lesen (p4 opened)", fr: "Relire les fichiers ouverts (p4 opened)", es: "Releer archivos abiertos (p4 opened)" },
|
||
"Loading…": { ru: "Загрузка…", de: "Lädt…", fr: "Chargement…", es: "Cargando…" },
|
||
"No open files yet.\nEdit assets in Unreal (Source Control → Perforce) — they show up here on their own.\n\nEdited files outside Perforce? Actions → “Rescan changes”.": {
|
||
ru: "Пока нет открытых файлов.\nМеняй ассеты в Unreal (Source Control → Perforce) — они появятся тут сами.\n\nПравил файлы мимо Perforce? Actions → «Найти изменения заново».",
|
||
de: "Noch keine offenen Dateien.\nBearbeite Assets in Unreal (Source Control → Perforce) — sie erscheinen hier von selbst.\n\nDateien außerhalb von Perforce geändert? Aktionen → „Änderungen neu suchen“.",
|
||
fr: "Aucun fichier ouvert pour l’instant.\nModifiez les assets dans Unreal (Source Control → Perforce) — ils apparaîtront ici automatiquement.\n\nFichiers modifiés hors Perforce ? Actions → « Rechercher les modifications ».",
|
||
es: "Aún no hay archivos abiertos.\nEdita assets en Unreal (Source Control → Perforce) — aparecerán aquí solos.\n\n¿Editaste archivos fuera de Perforce? Acciones → «Volver a buscar cambios».",
|
||
},
|
||
|
||
// commit box
|
||
"Summary: what changed…": { ru: "Кратко: что за изменение…", de: "Kurz: was wurde geändert…", fr: "Résumé : quel changement…", es: "Resumen: qué cambió…" },
|
||
"Description (optional)…": { ru: "Описание (необязательно)…", de: "Beschreibung (optional)…", fr: "Description (facultatif)…", es: "Descripción (opcional)…" },
|
||
"Commit changelist": { ru: "Commit changelist", de: "Changelist committen", fr: "Valider le changelist", es: "Confirmar changelist" },
|
||
"· {n} files": { ru: "· {n} файлов", de: "· {n} Dateien", fr: "· {n} fichiers", es: "· {n} archivos" },
|
||
"Commit = local (revertable). Send to the server — Submit, top-right.": { ru: "Commit = локально (revertable). Отправка на сервер — Submit вверху справа.", de: "Commit = lokal (rückgängig machbar). Zum Server senden — Submit oben rechts.", fr: "Commit = local (réversible). Envoyer au serveur — Submit en haut à droite.", es: "Commit = local (reversible). Enviar al servidor — Submit arriba a la derecha." },
|
||
|
||
// menus
|
||
"File": { ru: "Файл", de: "Datei", fr: "Fichier", es: "Archivo" },
|
||
"Connection": { ru: "Подключение", de: "Verbindung", fr: "Connexion", es: "Conexión" },
|
||
"Actions": { ru: "Действия", de: "Aktionen", fr: "Actions", es: "Acciones" },
|
||
"Tools": { ru: "Инструменты", de: "Werkzeuge", fr: "Outils", es: "Herramientas" },
|
||
"Help": { ru: "Справка", de: "Hilfe", fr: "Aide", es: "Ayuda" },
|
||
"Choose working folder…": { ru: "Выбрать рабочую папку…", de: "Arbeitsordner wählen…", fr: "Choisir le dossier de travail…", es: "Elegir carpeta de trabajo…" },
|
||
"Disconnect": { ru: "Отключиться", de: "Trennen", fr: "Se déconnecter", es: "Desconectar" },
|
||
"Rescan changes": { ru: "Найти изменения заново", de: "Änderungen neu suchen", fr: "Rechercher les modifications", es: "Volver a buscar cambios" },
|
||
"Commit (local)": { ru: "Commit (локально)", de: "Commit (lokal)", fr: "Commit (local)", es: "Commit (local)" },
|
||
"Revert All…": { ru: "Откатить всё…", de: "Alles zurücksetzen…", fr: "Tout annuler…", es: "Revertir todo…" },
|
||
"Settings…": { ru: "Настройки…", de: "Einstellungen…", fr: "Paramètres…", es: "Ajustes…" },
|
||
"About": { ru: "О программе", de: "Über", fr: "À propos", es: "Acerca de" },
|
||
|
||
// confirm dialogs
|
||
"Revert all changes?": { ru: "Откатить все изменения?", de: "Alle Änderungen zurücksetzen?", fr: "Annuler toutes les modifications ?", es: "¿Revertir todos los cambios?" },
|
||
"Edits in all {n} files will be undone. Local changes are lost permanently.": { ru: "Будут отменены правки во всех {n} файлах. Локальные изменения потеряются безвозвратно.", de: "Änderungen in allen {n} Dateien werden verworfen. Lokale Änderungen gehen endgültig verloren.", fr: "Les modifications de {n} fichiers seront annulées. Les changements locaux sont perdus définitivement.", es: "Se desharán los cambios en {n} archivos. Los cambios locales se pierden para siempre." },
|
||
"Revert all": { ru: "Откатить всё", de: "Alles zurücksetzen", fr: "Tout annuler", es: "Revertir todo" },
|
||
"Submit — send to the server": { ru: "Submit — отправить на сервер", de: "Submit — an Server senden", fr: "Submit — envoyer au serveur", es: "Submit — enviar al servidor" },
|
||
"{n} changelist(s) will go to the Perforce depot and become available to the team. This is a push — it cannot be undone.": { ru: "{n} changelist(ов) уйдут в депо Perforce и станут доступны команде. Это push — отменить нельзя.", de: "{n} Changelist(s) gehen ins Perforce-Depot und werden für das Team verfügbar. Das ist ein Push — nicht widerrufbar.", fr: "{n} changelist(s) iront dans le dépôt Perforce et seront disponibles pour l’équipe. C’est un push — irréversible.", es: "{n} changelist(s) irán al depósito Perforce y estarán disponibles para el equipo. Es un push — no se puede deshacer." },
|
||
"Submit {n}": { ru: "Отправить {n}", de: "{n} senden", fr: "Envoyer {n}", es: "Enviar {n}" },
|
||
"Changelist {a} of {b}": { ru: "Changelist {a} из {b}", de: "Changelist {a} von {b}", fr: "Changelist {a} sur {b}", es: "Changelist {a} de {b}" },
|
||
"Large assets take longer to upload — don’t close the window.": { ru: "Крупные ассеты заливаются дольше — не закрывай окно.", de: "Große Assets brauchen länger zum Hochladen — schließe das Fenster nicht.", fr: "Les gros assets prennent plus de temps à envoyer — ne fermez pas la fenêtre.", es: "Los assets grandes tardan más en subir — no cierres la ventana." },
|
||
"Revert file?": { ru: "Откатить файл?", de: "Datei zurücksetzen?", fr: "Annuler le fichier ?", es: "¿Revertir archivo?" },
|
||
"{name}\n\nLocal edits to this file will be lost.": { ru: "{name}\n\nЛокальные правки этого файла будут потеряны.", de: "{name}\n\nLokale Änderungen an dieser Datei gehen verloren.", fr: "{name}\n\nLes modifications locales de ce fichier seront perdues.", es: "{name}\n\nLos cambios locales de este archivo se perderán." },
|
||
"Revert": { ru: "Откатить", de: "Zurücksetzen", fr: "Annuler", es: "Revertir" },
|
||
"Discard changes": { ru: "Отменить изменения", de: "Änderungen verwerfen", fr: "Abandonner les modifications", es: "Descartar cambios" },
|
||
"Discard changes · {n} files": { ru: "Отменить изменения · {n} файлов", de: "Änderungen verwerfen · {n} Dateien", fr: "Abandonner · {n} fichiers", es: "Descartar · {n} archivos" },
|
||
"Discard changes?": { ru: "Отменить изменения?", de: "Änderungen verwerfen?", fr: "Abandonner les modifications ?", es: "¿Descartar cambios?" },
|
||
"Discard": { ru: "Отменить", de: "Verwerfen", fr: "Abandonner", es: "Descartar" },
|
||
"Local changes to {name} will be lost permanently — the file returns to the server version.": { ru: "Локальные изменения в {name} будут потеряны безвозвратно — файл вернётся к версии с сервера.", de: "Lokale Änderungen an {name} gehen endgültig verloren — die Datei kehrt zur Serverversion zurück.", fr: "Les modifications locales de {name} seront perdues définitivement — le fichier revient à la version du serveur.", es: "Los cambios locales en {name} se perderán para siempre — el archivo vuelve a la versión del servidor." },
|
||
"Discarded: {name}": { ru: "Отменено: {name}", de: "Verworfen: {name}", fr: "Abandonné : {name}", es: "Descartado: {name}" },
|
||
"Edit in VS Code": { ru: "Открыть в VS Code", de: "In VS Code öffnen", fr: "Ouvrir dans VS Code", es: "Abrir en VS Code" },
|
||
"Opening in VS Code…": { ru: "Открываю в VS Code…", de: "Wird in VS Code geöffnet…", fr: "Ouverture dans VS Code…", es: "Abriendo en VS Code…" },
|
||
"Revert changelist #{n}?": { ru: "Откатить changelist #{n}?", de: "Changelist #{n} zurücksetzen?", fr: "Annuler le changelist #{n} ?", es: "¿Revertir changelist #{n}?" },
|
||
"Perforce will create a NEW changelist that undoes #{n} and submit it to the server. History is kept (like “Revert” in GitHub Desktop).\n\n“{desc}”": { ru: "Perforce создаст НОВЫЙ changelist, отменяющий изменения из #{n}, и засабмитит его на сервер. История сохранится (как «Revert» в GitHub Desktop).\n\n«{desc}»", de: "Perforce erstellt eine NEUE Changelist, die #{n} rückgängig macht, und sendet sie an den Server. Der Verlauf bleibt erhalten (wie „Revert“ in GitHub Desktop).\n\n„{desc}“", fr: "Perforce créera un NOUVEAU changelist qui annule #{n} et l’enverra au serveur. L’historique est conservé (comme « Revert » dans GitHub Desktop).\n\n« {desc} »", es: "Perforce creará un NUEVO changelist que deshace #{n} y lo enviará al servidor. El historial se conserva (como «Revert» en GitHub Desktop).\n\n«{desc}»" },
|
||
"Revert #{n}": { ru: "Откатить #{n}", de: "#{n} zurücksetzen", fr: "Annuler #{n}", es: "Revertir #{n}" },
|
||
"no description": { ru: "без описания", de: "keine Beschreibung", fr: "sans description", es: "sin descripción" },
|
||
"Cancel": { ru: "Отмена", de: "Abbrechen", fr: "Annuler", es: "Cancelar" },
|
||
|
||
// toasts
|
||
"No session data for the workspace list": { ru: "Нет данных сессии для списка workspace", de: "Keine Sitzungsdaten für die Workspace-Liste", fr: "Aucune donnée de session pour la liste des workspaces", es: "No hay datos de sesión para la lista de workspaces" },
|
||
"Active workspace: {c}": { ru: "Активный workspace: {c}", de: "Aktiver Workspace: {c}", fr: "Workspace actif : {c}", es: "Workspace activo: {c}" },
|
||
"Get Latest: {msg}": { ru: "Get Latest: {msg}", de: "Get Latest: {msg}", fr: "Get Latest : {msg}", es: "Get Latest: {msg}" },
|
||
"Added/updated in changelist: {n}": { ru: "В changelist добавлено/обновлено: {n}", de: "Zur Changelist hinzugefügt/aktualisiert: {n}", fr: "Ajouté/mis à jour dans le changelist : {n}", es: "Añadido/actualizado en el changelist: {n}" },
|
||
"No changes to add": { ru: "Нет изменений для добавления", de: "Keine Änderungen zum Hinzufügen", fr: "Aucune modification à ajouter", es: "No hay cambios para añadir" },
|
||
"All changes reverted.": { ru: "Все изменения откачены.", de: "Alle Änderungen zurückgesetzt.", fr: "Toutes les modifications annulées.", es: "Todos los cambios revertidos." },
|
||
"Committed locally · changelist {cl}. Press Submit at the top to send it to the server.": { ru: "Закоммичено локально · changelist {cl}. Нажми Submit вверху, чтобы отправить на сервер.", de: "Lokal committed · Changelist {cl}. Drücke oben Submit, um an den Server zu senden.", fr: "Validé localement · changelist {cl}. Appuyez sur Submit en haut pour l’envoyer au serveur.", es: "Confirmado localmente · changelist {cl}. Pulsa Submit arriba para enviarlo al servidor." },
|
||
"Sent to the server: {n} changelist(s).": { ru: "Отправлено на сервер: {n} changelist(ов).", de: "An Server gesendet: {n} Changelist(s).", fr: "Envoyé au serveur : {n} changelist(s).", es: "Enviado al servidor: {n} changelist(s)." },
|
||
"Reverted: {name}": { ru: "Откачено: {name}", de: "Zurückgesetzt: {name}", fr: "Annulé : {name}", es: "Revertido: {name}" },
|
||
"Changelist #{n} reverted by a new changelist.": { ru: "Changelist #{n} откачен новым changelist'ом.", de: "Changelist #{n} durch eine neue Changelist zurückgesetzt.", fr: "Changelist #{n} annulé par un nouveau changelist.", es: "Changelist #{n} revertido por un nuevo changelist." },
|
||
"Path not set": { ru: "Путь не определён", de: "Pfad nicht festgelegt", fr: "Chemin non défini", es: "Ruta no definida" },
|
||
"{what} copied": { ru: "{what} скопировано", de: "{what} kopiert", fr: "{what} copié", es: "{what} copiado" },
|
||
"Copy failed": { ru: "Не удалось скопировать", de: "Kopieren fehlgeschlagen", fr: "Échec de la copie", es: "Error al copiar" },
|
||
"Workspace name": { ru: "Имя workspace", de: "Workspace-Name", fr: "Nom du workspace", es: "Nombre del workspace" },
|
||
"Path": { ru: "Путь", de: "Pfad", fr: "Chemin", es: "Ruta" },
|
||
"Number": { ru: "Номер", de: "Nummer", fr: "Numéro", es: "Número" },
|
||
"Description": { ru: "Описание", de: "Beschreibung", fr: "Description", es: "Descripción" },
|
||
"Found and added to Changes: {n}": { ru: "Найдено и добавлено в Changes: {n}", de: "Gefunden und zu Änderungen hinzugefügt: {n}", fr: "Trouvé et ajouté aux modifications : {n}", es: "Encontrado y añadido a Cambios: {n}" },
|
||
"No new or changed files found.": { ru: "Новых или изменённых файлов не найдено.", de: "Keine neuen oder geänderten Dateien gefunden.", fr: "Aucun fichier nouveau ou modifié trouvé.", es: "No se encontraron archivos nuevos o modificados." },
|
||
|
||
// drop zone
|
||
"Drop to add to Perforce": { ru: "Отпусти, чтобы добавить в Perforce", de: "Loslassen, um zu Perforce hinzuzufügen", fr: "Relâchez pour ajouter à Perforce", es: "Suelta para añadir a Perforce" },
|
||
|
||
// app modal — workspaces
|
||
"Choose workspace": { ru: "Выбор workspace", de: "Workspace wählen", fr: "Choisir un workspace", es: "Elegir workspace" },
|
||
"No workspaces available": { ru: "Нет доступных workspace", de: "Keine Workspaces verfügbar", fr: "Aucun workspace disponible", es: "No hay workspaces disponibles" },
|
||
"Active: {c}": { ru: "Активный: {c}", de: "Aktiv: {c}", fr: "Actif : {c}", es: "Activo: {c}" },
|
||
// app modal — scope
|
||
".. up": { ru: ".. вверх", de: ".. hoch", fr: ".. haut", es: ".. arriba" },
|
||
"No subfolders": { ru: "Вложенных папок нет", de: "Keine Unterordner", fr: "Aucun sous-dossier", es: "Sin subcarpetas" },
|
||
"Work in: {path}": { ru: "Работать в: {path}", de: "Arbeiten in: {path}", fr: "Travailler dans : {path}", es: "Trabajar en: {path}" },
|
||
"Work in the whole workspace (//…)": { ru: "Работать во всём workspace (//…)", de: "Im ganzen Workspace arbeiten (//…)", fr: "Travailler dans tout le workspace (//…)", es: "Trabajar en todo el workspace (//…)" },
|
||
// app modal — settings
|
||
"Settings": { ru: "Настройки", de: "Einstellungen", fr: "Paramètres", es: "Ajustes" },
|
||
"Language": { ru: "Язык", de: "Sprache", fr: "Langue", es: "Idioma" },
|
||
"Interface scale": { ru: "Масштаб интерфейса", de: "Oberflächenskalierung", fr: "Échelle de l’interface", es: "Escala de interfaz" },
|
||
"Reset": { ru: "Сбросить", de: "Zurücksetzen", fr: "Réinitialiser", es: "Restablecer" },
|
||
// window menu + log panel
|
||
"Window": { ru: "Окно", de: "Fenster", fr: "Fenêtre", es: "Ventana" },
|
||
"Log": { ru: "Лог", de: "Protokoll", fr: "Journal", es: "Registro" },
|
||
"Clear": { ru: "Очистить", de: "Leeren", fr: "Effacer", es: "Limpiar" },
|
||
"item(s)": { ru: "элем.", de: "Einträge", fr: "élément(s)", es: "elemento(s)" },
|
||
"No commands yet.": { ru: "Пока нет команд.", de: "Noch keine Befehle.", fr: "Aucune commande pour l’instant.", es: "Aún no hay comandos." },
|
||
"Recent commands": { ru: "Последние команды", de: "Letzte Befehle", fr: "Commandes récentes", es: "Comandos recientes" },
|
||
"Light ☀": { ru: "Светлая ☀", de: "Hell ☀", fr: "Clair ☀", es: "Claro ☀" },
|
||
"Dark ☾": { ru: "Тёмная ☾", de: "Dunkel ☾", fr: "Sombre ☾", es: "Oscuro ☾" },
|
||
"Server version": { ru: "Версия сервера", de: "Serverversion", fr: "Version du serveur", es: "Versión del servidor" },
|
||
// about
|
||
"Exbyte Depot — native Perforce client": { ru: "Exbyte Depot — нативный клиент Perforce", de: "Exbyte Depot — nativer Perforce-Client", fr: "Exbyte Depot — client Perforce natif", es: "Exbyte Depot — cliente nativo de Perforce" },
|
||
"Built by Exbyte Studios": { ru: "Собственная разработка Exbyte Studios", de: "Entwickelt von Exbyte Studios", fr: "Développé par Exbyte Studios", es: "Desarrollado por Exbyte Studios" },
|
||
|
||
// change detail
|
||
"Select a changelist in History": { ru: "Выберите changelist в History", de: "Wähle eine Changelist im Verlauf", fr: "Sélectionnez un changelist dans l’historique", es: "Selecciona un changelist en el historial" },
|
||
"(no description)": { ru: "(без описания)", de: "(keine Beschreibung)", fr: "(sans description)", es: "(sin descripción)" },
|
||
"{user} · {time} · {n} file(s)": { ru: "{user} · {time} · {n} файл(ов)", de: "{user} · {time} · {n} Datei(en)", fr: "{user} · {time} · {n} fichier(s)", es: "{user} · {time} · {n} archivo(s)" },
|
||
"Loading file list…": { ru: "Загрузка списка файлов…", de: "Dateiliste wird geladen…", fr: "Chargement de la liste des fichiers…", es: "Cargando lista de archivos…" },
|
||
// history list
|
||
"Loading history…": { ru: "Загрузка истории…", de: "Verlauf wird geladen…", fr: "Chargement de l’historique…", es: "Cargando historial…" },
|
||
"No submitted changes.": { ru: "Нет засабмиченных изменений.", de: "Keine übermittelten Änderungen.", fr: "Aucune modification envoyée.", es: "No hay cambios enviados." },
|
||
// history context menu
|
||
"Open this changelist": { ru: "Открыть этот changelist", de: "Diese Changelist öffnen", fr: "Ouvrir ce changelist", es: "Abrir este changelist" },
|
||
"Revert (undo) #{n}": { ru: "Откатить (revert) #{n}", de: "Zurücksetzen (undo) #{n}", fr: "Annuler (revert) #{n}", es: "Revertir (undo) #{n}" },
|
||
"Copy number #{n}": { ru: "Скопировать номер #{n}", de: "Nummer #{n} kopieren", fr: "Copier le numéro #{n}", es: "Copiar número #{n}" },
|
||
"Copy description": { ru: "Скопировать описание", de: "Beschreibung kopieren", fr: "Copier la description", es: "Copiar descripción" },
|
||
|
||
// preview
|
||
"Select a file on the left": { ru: "Выберите файл слева", de: "Wähle links eine Datei", fr: "Sélectionnez un fichier à gauche", es: "Selecciona un archivo a la izquierda" },
|
||
"Loading diff…": { ru: "Загрузка diff…", de: "Diff wird geladen…", fr: "Chargement du diff…", es: "Cargando diff…" },
|
||
"No text differences (or binary file).": { ru: "Нет текстовых отличий (или бинарный файл).", de: "Keine Textunterschiede (oder Binärdatei).", fr: "Aucune différence de texte (ou fichier binaire).", es: "Sin diferencias de texto (o archivo binario)." },
|
||
"Binary file — no code preview.": { ru: "Бинарный файл — превью кода нет.", de: "Binärdatei — keine Code-Vorschau.", fr: "Fichier binaire — pas d’aperçu du code.", es: "Archivo binario — sin vista previa de código." },
|
||
"File is too large to preview.": { ru: "Файл слишком большой для превью.", de: "Datei zu groß für die Vorschau.", fr: "Fichier trop volumineux pour l’aperçu.", es: "Archivo demasiado grande para previsualizar." },
|
||
"Diff": { ru: "Diff", de: "Diff", fr: "Diff", es: "Diff" },
|
||
"New file": { ru: "Новый файл", de: "Neue Datei", fr: "Nouveau fichier", es: "Archivo nuevo" },
|
||
"Text": { ru: "Текст", de: "Text", fr: "Texte", es: "Texto" },
|
||
"{n} lines": { ru: "{n} строк", de: "{n} Zeilen", fr: "{n} lignes", es: "{n} líneas" },
|
||
"Image": { ru: "Изображение", de: "Bild", fr: "Image", es: "Imagen" },
|
||
"Resolution": { ru: "Разрешение", de: "Auflösung", fr: "Résolution", es: "Resolución" },
|
||
"Format": { ru: "Формат", de: "Format", fr: "Format", es: "Formato" },
|
||
"Source": { ru: "Источник", de: "Quelle", fr: "Source", es: "Fuente" },
|
||
"working copy": { ru: "рабочая копия", de: "Arbeitskopie", fr: "copie de travail", es: "copia de trabajo" },
|
||
"Unreal · embedded thumbnail": { ru: "Unreal · вшитая миниатюра", de: "Unreal · eingebettetes Vorschaubild", fr: "Unreal · miniature intégrée", es: "Unreal · miniatura incrustada" },
|
||
"Reading asset…": { ru: "Читаю ассет…", de: "Asset wird gelesen…", fr: "Lecture de l’asset…", es: "Leyendo asset…" },
|
||
"This asset has no embedded thumbnail. Interactive 3D works for FBX / OBJ / GLB / GLTF / STL — export the model to one of these formats.": { ru: "В этом ассете нет вшитой миниатюры. Интерактивный 3D работает для FBX / OBJ / GLB / GLTF / STL — экспортни модель в один из этих форматов.", de: "Dieses Asset hat kein eingebettetes Vorschaubild. Interaktives 3D funktioniert für FBX / OBJ / GLB / GLTF / STL — exportiere das Modell in eines dieser Formate.", fr: "Cet asset n’a pas de miniature intégrée. La 3D interactive fonctionne pour FBX / OBJ / GLB / GLTF / STL — exportez le modèle dans l’un de ces formats.", es: "Este asset no tiene miniatura incrustada. El 3D interactivo funciona con FBX / OBJ / GLB / GLTF / STL — exporta el modelo a uno de estos formatos." },
|
||
"Type": { ru: "Тип", de: "Typ", fr: "Type", es: "Tipo" },
|
||
"Preview": { ru: "Превью", de: "Vorschau", fr: "Aperçu", es: "Vista previa" },
|
||
"thumbnail": { ru: "миниатюра", de: "Vorschaubild", fr: "miniature", es: "miniatura" },
|
||
"none": { ru: "нет", de: "keine", fr: "aucune", es: "ninguna" },
|
||
"Revision": { ru: "Ревизия", de: "Revision", fr: "Révision", es: "Revisión" },
|
||
|
||
// model viewer
|
||
"drag — rotate · wheel — zoom · right-click — pan": { ru: "тащи — вращать · колесо — зум · ПКМ — панорама", de: "ziehen — drehen · Rad — zoomen · Rechtsklick — schwenken", fr: "glisser — pivoter · molette — zoom · clic droit — panoramique", es: "arrastra — girar · rueda — zoom · clic derecho — panorámica" },
|
||
"Loading model…": { ru: "Загрузка модели…", de: "Modell wird geladen…", fr: "Chargement du modèle…", es: "Cargando modelo…" },
|
||
"Format not supported by the viewer": { ru: "Формат не поддерживается вьювером", de: "Format vom Viewer nicht unterstützt", fr: "Format non pris en charge par la visionneuse", es: "Formato no compatible con el visor" },
|
||
"Collada: empty scene": { ru: "Collada: пустая сцена", de: "Collada: leere Szene", fr: "Collada : scène vide", es: "Collada: escena vacía" },
|
||
"Triangles": { ru: "Треугольники", de: "Dreiecke", fr: "Triangles", es: "Triángulos" },
|
||
"Vertices": { ru: "Вершины", de: "Ecken", fr: "Sommets", es: "Vértices" },
|
||
"Meshes · Materials": { ru: "Меши · Материалы", de: "Meshes · Materialien", fr: "Maillages · Matériaux", es: "Mallas · Materiales" },
|
||
"Render": { ru: "Рендер", de: "Render", fr: "Rendu", es: "Render" },
|
||
"Wireframe": { ru: "Каркас", de: "Drahtgitter", fr: "Filaire", es: "Malla" },
|
||
"Grid": { ru: "Сетка", de: "Raster", fr: "Grille", es: "Cuadrícula" },
|
||
"Reset view": { ru: "Сбросить вид", de: "Ansicht zurücksetzen", fr: "Réinitialiser la vue", es: "Restablecer vista" },
|
||
|
||
// updater
|
||
"Update available": { ru: "Доступно обновление", de: "Update verfügbar", fr: "Mise à jour disponible", es: "Actualización disponible" },
|
||
"Later": { ru: "Позже", de: "Später", fr: "Plus tard", es: "Más tarde" },
|
||
"Downloading… {pct}%": { ru: "Загрузка… {pct}%", de: "Wird geladen… {pct}%", fr: "Téléchargement… {pct}%", es: "Descargando… {pct}%" },
|
||
"Installed — restarting…": { ru: "Установлено — перезапускаю…", de: "Installiert — Neustart…", fr: "Installé — redémarrage…", es: "Instalado — reiniciando…" },
|
||
"Update now": { ru: "Обновить сейчас", de: "Jetzt aktualisieren", fr: "Mettre à jour", es: "Actualizar ahora" },
|
||
};
|
||
|
||
export function t(en: string, vars?: Record<string, string | number>): string {
|
||
let s = D[en]?.[LANG] ?? en;
|
||
if (vars) for (const k in vars) s = s.split("{" + k + "}").join(String(vars[k]));
|
||
return s;
|
||
}
|