// 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>; const D: Record = { // 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 { let s = D[en]?.[LANG] ?? en; if (vars) for (const k in vars) s = s.split("{" + k + "}").join(String(vars[k])); return s; }