diff --git a/js/i18n.js b/js/i18n.js index 76ce246..06dc9a2 100644 --- a/js/i18n.js +++ b/js/i18n.js @@ -2,14 +2,15 @@ // Only display names live here; full strings are lazy-loaded per language. export const TRANSLATIONS = { - en: { 'lang.name': 'English' }, de: { 'lang.name': 'Deutsch' }, - it: { 'lang.name': 'Italiano' }, + en: { 'lang.name': 'English' }, es: { 'lang.name': 'Español (beta)' }, - pt: { 'lang.name': 'Português (beta)' }, fr: { 'lang.name': 'Français' }, + it: { 'lang.name': 'Italiano' }, ja: { 'lang.name': '日本語 (beta)' }, ko: { 'lang.name': '한국어' }, + pt: { 'lang.name': 'Português (beta)' }, + ru: { 'lang.name': 'Русский' } }; // ── Module state ────────────────────────────────────────────────────────────── diff --git a/js/i18n/ru.js b/js/i18n/ru.js new file mode 100644 index 0000000..56be22b --- /dev/null +++ b/js/i18n/ru.js @@ -0,0 +1,145 @@ +export default { + "theme.dark": "Тёмная тема", + "theme.light": "Светлая тема", + "theme.toggleTitle": "Переключить светлый / тёмный режим", + "theme.toggleAriaLabel": "Переключить светлый/тёмный режим", + "dropHint.text": "Перетащите сюда файл .stl, .obj или .3mf
или ", + "ui.wireframe": "Каркас", + "ui.perspective": "Перспективный вид", + "ui.controlsHint": "ЛКМ + перетаскивание: вращение · ПКМ + перетаскивание: панорамирование · Колесо: масштаб", + "ui.meshInfo": "{n} треугольников · {mb} МБ · {sx} × {sy} × {sz} мм", + "ui.loadStl": "Загрузить модель…", + "ui.localProcessingNote": "Вся обработка выполняется локально в браузере — данные никуда не загружаются.", + "sections.displacementMap": "Карта рельефа", + "ui.uploadCustomMap": "Загрузить свою карту", + "ui.noMapSelected": "Карта не выбрана", + "sections.projection": "Проекция", + "labels.mode": "Режим", + "projection.triplanar": "Трипланарная", + "projection.cubic": "Кубическая (Box)", + "projection.cylindrical": "Цилиндрическая", + "projection.spherical": "Сферическая", + "projection.planarXY": "Плоская XY", + "projection.planarXZ": "Плоская XZ", + "projection.planarYZ": "Плоская YZ", + "sections.transform": "Трансформация", + "labels.scaleU": "Масштаб U", + "labels.scaleV": "Масштаб V", + "labels.offsetU": "Смещение U", + "labels.offsetV": "Смещение V", + "labels.rotation": "Поворот", + "tooltips.proportionalScaling": "Пропорциональное масштабирование (U = V)", + "tooltips.proportionalScalingAria": "Пропорциональное масштабирование (U = V)", + "sections.displacement": "Глубина текстуры", + "labels.amplitude": "Амплитуда", + "labels.seamBlend": "Сглаживание шва ⓘ", + "tooltips.seamBlend": "Смягчает жёсткий шов в местах стыка граней проекции. Эффективно для режимов Cubic и Cylindrical.", + "labels.transitionSmoothing": "Сглаживание перехода ⓘ", + "tooltips.transitionSmoothing": "Ширина зоны смешивания возле краёв шва. Меньшие значения держат переход ближе к шву; большие — расширяют зону смешивания.", + "labels.textureSmoothing": "Сглаживание текстуры ⓘ", + "tooltips.textureSmoothing": "Применяет гауссово размытие к карте рельефа. Более высокие значения дают более мягкие и плавные детали поверхности. 0 = выкл.", + "labels.capAngle": "Угол крышки ⓘ", + "tooltips.capAngle": "Угол (в градусах) от вертикали, при котором начинает применяться проекция верхней/нижней крышки. Меньшие значения ограничивают проекцию почти плоскими гранями.", + "sections.masking": "Маскирование", + "sections.maskAngles": "По углу ⓘ", + "tooltips.maskAngles": "0° = без маскирования. Поверхности в пределах этого угла от горизонтали не будут текстурироваться.", + "labels.bottomFaces": "Нижние грани", + "tooltips.bottomFaces": "Не наносить текстуру на поверхности, направленные вниз, в пределах этого угла от горизонтали", + "labels.topFaces": "Верхние грани", + "tooltips.topFaces": "Не наносить текстуру на поверхности, направленные вверх, в пределах этого угла от горизонтали", + "sections.surfaceMasking": "По поверхности ⓘ", + "sections.surfaceSelection": "Выбор поверхности", + "tooltips.surfaceMasking": "Маскируйте поверхности, чтобы управлять тем, какие области будут получать рельеф.", + "tooltips.surfaceSelection": "Выбранные поверхности отображаются зелёным и будут единственными, на которые при экспорте будет применён рельеф.", + "excl.modeExclude": "Исключить", + "excl.modeExcludeTitle": "Режим исключения: закрашенные поверхности не будут получать рельеф", + "excl.modeIncludeOnly": "Только включённые", + "excl.modeIncludeOnlyTitle": "Режим только включённых: рельеф будет применяться только к закрашенным поверхностям", + "excl.toolBrush": "Кисть", + "excl.toolBrushTitle": "Кисть: закрашивать треугольники для исключения", + "excl.toolFill": "Заливка", + "excl.toolFillTitle": "Заливка: заполнение поверхности до порогового угла", + "excl.shiftHint": "Удерживайте Shift, чтобы стереть", + "labels.type": "Тип", + "brushType.single": "Одиночная", + "brushType.circle": "Круг", + "labels.size": "Размер", + "labels.maxAngle": "Макс. угол", + "tooltips.maxAngle": "Максимальный двугранный угол между соседними треугольниками, через который будет проходить заливка", + "ui.clearAll": "Очистить всё", + "excl.initExcluded": "0 граней замаскировано", + "excl.faceExcluded": "{n} грань замаскирована", + "excl.facesExcluded": "{n} граней замаскировано", + "excl.faceSelected": "{n} грань выбрана", + "excl.facesSelected": "{n} граней выбрано", + "excl.hintExclude": "Замаскированные поверхности отображаются оранжевым и не будут получать рельеф при экспорте.", + "excl.hintInclude": "Выбранные поверхности отображаются зелёным и будут единственными, на которые при экспорте будет применён рельеф.", + "precision.label": "Точность (Beta) ⓘ", + "precision.labelTitle": "Разбить сетку в фоне, чтобы кисть работала с более мелкой детализацией", + "precision.outdated": "⚠ Устарело", + "precision.refreshTitle": "Повторно разбить сетку в соответствии с текущим размером кисти", + "precision.triCount": "{n} △", + "precision.refining": "Уточнение…", + "precision.warningBody": "Оценочно ~{n} треугольников. Это может замедлить браузер. Продолжить?", + "labels.boundaryFalloff": "Плавная маска ⓘ", + "tooltips.boundaryFalloff": "Постепенно снижает рельеф до нуля возле границ маски, предотвращая наложение треугольников в местах стыка текстурированных и нетекстурированных областей.", + "labels.symmetricDisplacement": "Симметричный рельеф ⓘ", + "tooltips.symmetricDisplacement": "Если включено, 50% серого = без смещения; белый выталкивает наружу, чёрный вдавливает внутрь. Объём детали остаётся примерно постоянным.", + "labels.displacementPreview": "3D-просмотр ⓘ", + "tooltips.displacementPreview": "Разбивает сетку и смещает вершины в реальном времени, чтобы можно было оценить фактическую глубину. На сложных моделях сильно нагружает GPU.", + "ui.placeOnFace": "Положить на грань", + "ui.placeOnFaceTitle": "Нажмите на грань, чтобы ориентировать её вниз на стол 3D-принтера", + "progress.subdividingPreview": "Подготовка предпросмотра…", + "warnings.amplitudeOverlap": "⚠ Амплитуда превышает 10% от наименьшего размера модели — в экспортируемом STL возможны пересечения геометрии.", + "sections.export": "Экспорт ⓘ", + "tooltips.export": "Меньшая длина ребра = более детализированный рельеф. Затем результат упрощается до лимита треугольников.", + "labels.resolution": "Разрешение", + "tooltips.resolution": "Рёбра длиннее этого значения будут разбиты при экспорте", + "labels.outputTriangles": "Треугольники на выходе", + "tooltips.outputTriangles": "Сетка сначала полностью разбивается, затем упрощается до этого числа", + "warnings.safetyCapHit": "⚠ Во время разбиения достигнут безопасный лимит в 20 млн треугольников — результат может оказаться грубее, чем заданная длина ребра.", + "ui.exportStl": "Экспорт STL", + "progress.subdividing": "Разбиение сетки…", + "progress.refining": "Уточнение: {cur} треугольников, самое длинное ребро {edge}", + "progress.applyingDisplacement": "Применение рельефа к {n} треугольникам…", + "progress.displacingVertices": "Смещение вершин…", + "progress.decimatingTo": "Упрощение {from} → {to} треугольников…", + "progress.decimating": "Упрощение: {cur} → {to} треугольников", + "progress.writingStl": "Запись STL…", + "progress.done": "Готово!", + "progress.processing": "Обработка…", + "license.btn": "Лицензия и условия", + "license.title": "Лицензия и условия", + "license.item1": "Можно использовать бесплатно для любых целей, включая коммерческое использование (например, нанесение текстуры на STL для клиентов или изделий).", + "license.item2": "Указание авторства приветствуется, но не обязательно при использовании этого инструмента без изменений.", + "license.item3": "Поддержите проект! Загляните в CNCKitchen.STORE или сделайте пожертвование через PayPal.", + "license.item4": "Этот инструмент предоставляется как есть, без каких-либо гарантий. Используйте на свой страх и риск.", + "license.item5": "Поддержка не предоставляется. Автор не обязан исправлять ошибки, отвечать на вопросы или обновлять этот инструмент. Тем не менее, сообщения об ошибках и предложения по улучшению всегда приветствуются по адресу texturizer@cnckitchen.com.", + "license.item6": "Автор не несёт ответственности за любой ущерб, потерю данных или проблемы, возникшие при использовании этого инструмента.", + "license.item7": "Хотите лицензировать этот инструмент или встроить его в свой бизнес или сайт? Свяжитесь с нами по адресу contact@cnckitchen.com.", + "license.item8": "Исходный код доступен на GitHub.", + "imprint.btn": "Юридическая информация и конфиденциальность", + "imprint.title": "Юридическая информация и политика конфиденциальности", + "imprint.sectionImprint": "Реквизиты (Impressum)", + "imprint.info": "CNC Kitchen
Stefan Hermann
Bahnhofstr. 2
88145 Hergatz
Germany", + "imprint.contact": "Email: contact@cnckitchen.com
Телефон: +49 175 2011824
Номер телефона предназначен только для юридических и деловых вопросов — не для поддержки.", + "imprint.odr": "Платформа онлайн-разрешения споров ЕС: https://ec.europa.eu/consumers/odr", + "imprint.sectionPrivacy": "Политика конфиденциальности (Datenschutzerklärung)", + "imprint.privacyIntro": "Ответственное лицо (Verantwortlicher gem. Art. 4 Abs. 7 DSGVO): Stefan Hermann, Bahnhofstr. 2, 88145 Hergatz, Germany.", + "imprint.privacyHosting": "Этот сайт размещён на GitHub Pages (GitHub Inc. / Microsoft Corp., 88 Colin P Kelly Jr St, San Francisco, CA 94107, USA). При посещении сайта GitHub может обрабатывать ваш IP-адрес в серверных журналах. Правовое основание: Art. 6(1)(f) DSGVO (законный интерес в предоставлении сайта). См. Заявление о конфиденциальности GitHub.", + "imprint.privacyLocal": "Этот инструмент сохраняет пользовательские настройки (язык, тема) в localStorage браузера. Эти данные не покидают ваше устройство и не передаются на сервер.", + "imprint.privacyNoCookies": "Этот сайт не использует cookies, аналитику или какие-либо технологии отслеживания.", + "imprint.privacyExternal": "На сайте есть ссылки на внешние ресурсы (например, CNCKitchen.STORE, PayPal). У этих сайтов свои политики конфиденциальности, на которые мы не влияем.", + "imprint.privacyRights": "В соответствии с GDPR у вас есть право на доступ, исправление, удаление, ограничение обработки, переносимость данных, а также право подать жалобу в надзорный орган.", + "sponsor.title": "Спасибо, что используете BumpMesh от CNC Kitchen!", + "sponsor.body": "Этот инструмент предоставляется совершенно бесплатно компанией CNC Kitchen.
Пока ваш STL обрабатывается, загляните в магазин, который помогает нам и дальше делать для вас классные вещи.", + "sponsor.visitStore": "🛒 Перейти в CNCKitchen.STORE", + "sponsor.donate": "💙 Пожертвовать через PayPal", + "sponsor.dontShow": "Больше не показывать", + "sponsor.closeAndContinue": "Закрыть и продолжить", + "cta.store": "Поддержите проект! Загляните в CNCKitchen.STORE или сделайте пожертвование через PayPal", + "cta.storeDismiss": "Закрыть", + "alerts.loadFailed": "Не удалось загрузить модель: {msg}", + "alerts.exportFailed": "Экспорт не удался: {msg}", + "alerts.fileTooLarge": "Файл слишком большой ({size} МБ). Максимум: {max} МБ." +}; \ No newline at end of file