diff --git a/web/src/lib/i18n/dict.ts b/web/src/lib/i18n/dict.ts index 18555b3..206177b 100644 --- a/web/src/lib/i18n/dict.ts +++ b/web/src/lib/i18n/dict.ts @@ -32,11 +32,13 @@ export type HeaderStrings = { catalog: string; sectionsAria: string; footerNote: string; + home: string; + uiKit: string; }; export type Dict = { header: HeaderStrings; - categories: Record; + categories: Record; home: Record; catalog: Record; toolPage: Record; diff --git a/web/src/lib/i18n/en.ts b/web/src/lib/i18n/en.ts index ee7f100..d427e60 100644 --- a/web/src/lib/i18n/en.ts +++ b/web/src/lib/i18n/en.ts @@ -5,10 +5,13 @@ export const en: Dict = { workspace: "Workspace", catalog: "Catalog", sectionsAria: "Sections", + home: "Home page", + uiKit: "UI Kit", footerNote: "All operations run locally in your browser — your files are never uploaded anywhere.", }, categories: { + all: "All", convert: "Convert", alpha: "Transparency", color: "Color", @@ -30,7 +33,9 @@ export const en: Dict = { metaDescription: "Full catalog of PNG utilities: convert, transparency, color, geometry, analysis and image generation.", heading: "Tool catalog", - lead: "{count} utilities for working with PNG. Everything runs locally in your browser.", + lead: "Focused utilities for working with PNG. Inspect, transform, and export — locally in your browser.", + toolsAvailable: "Tools available", + toolsCount: "Tools", }, toolPage: { fallbackTitle: "Tool", @@ -53,6 +58,9 @@ export const en: Dict = { }, sourceCard: { replaceImage: "Replace image", + chooseImage: "choose an image", + noSource: "no source — configure the parameters", + alt: "Source image", }, resultCard: { emptyTitle: "The result will appear here", @@ -62,9 +70,15 @@ export const en: Dict = { recalc: "Recalculating…", nextTool: "⛓ Next tool", breakChain: "✂ Break the chain", + noResult: "no result yet", + parts: "parts", + format: "Format", + alt: "Result image", }, paramsCard: { noParams: "This tool has no parameters — the result is ready as is.", + configureOutput: "Configure output", + noSchema: "This tool has no schema yet.", }, textInput: { heading: "Text", @@ -78,6 +92,17 @@ export const en: Dict = { copy: "Copy", downloadTxt: "Download .txt", }, + actions: { + generate: "Generate", + generating: "Generating…", + openImage: "Open image", + downloadResult: "Download result", + }, + textSource: { + placeholder: "Paste base64 / hex / bytes…", + trySample: "Try sample", + render: "Render text", + }, download: { busy: "Preparing file…", file: "Download .{ext}", @@ -92,6 +117,8 @@ export const en: Dict = { dropZone: { pickDefault: "Drop an image here or click to choose a file", overlayDefault: "Release the file to replace the image", + pickTitle: "Drop a PNG here", + pickHint: "or click to browse — processed locally", }, search: { placeholder: "Find a tool…", @@ -109,6 +136,25 @@ export const en: Dict = { overlayTitle: "Watermark", overlayDrop: "Drop a watermark PNG or click", overlayRemove: "Remove watermark", + autoUpdate: "updates automatically", + width: "Width", + height: "Height", + from: "From", + to: "To", + font: "Font", + size: "Size", + color: "Color", + bold: "Bold", + fontSans: "Sans", + fontSerif: "Serif", + fontMono: "Mono", + opacity: "Opacity", + angle: "Angle", + backingPlate: "Backing plate", + addColor: "+ Add color", + removeColor: "Remove color", + themeToggle: "Toggle theme", + language: "Language", }, errors: { noImageRun: "This tool does not process images", @@ -151,7 +197,10 @@ export const en: Dict = { cropSize: "Crop width and height must be positive", sizePositive: "Dimensions must be positive and finite", tooManyParts: "Too many parts ({count}). Maximum is 1000.", + toolUnknown: 'No tool is registered under "{id}".', }, + fields: {}, + groups: {}, tools: { "png-file-size": { results: { diff --git a/web/src/lib/i18n/ru.ts b/web/src/lib/i18n/ru.ts index 15b1669..74cdd73 100644 --- a/web/src/lib/i18n/ru.ts +++ b/web/src/lib/i18n/ru.ts @@ -1,14 +1,17 @@ -import type { Dict } from "./dict"; +import type { Dict } from "./dict"; export const ru: Dict = { header: { workspace: "Рабочая область", catalog: "Каталог", sectionsAria: "Разделы", + home: "Главная", + uiKit: "UI Kit", footerNote: "Все операции выполняются локально в вашем браузере — файлы никуда не отправляются.", }, categories: { + all: "Все", convert: "Конвертация", alpha: "Прозрачность", color: "Цвет", @@ -31,7 +34,9 @@ export const ru: Dict = { metaDescription: "Полный каталог PNG-утилит: конвертация, прозрачность, цвет, геометрия, анализ и генерация изображений.", heading: "Каталог инструментов", - lead: "{count} утилит для работы с PNG. Все операции выполняются локально в браузере.", + lead: "Утилиты для работы с PNG. Анализируйте, преобразуйте и экспортируйте — локально в браузере.", + toolsAvailable: "Инструментов доступно", + toolsCount: "Инструментов", }, toolPage: { fallbackTitle: "Инструмент", @@ -54,6 +59,9 @@ export const ru: Dict = { }, sourceCard: { replaceImage: "Заменить изображение", + chooseImage: "выберите изображение", + noSource: "нет источника — настройте параметры", + alt: "Исходное изображение", }, resultCard: { emptyTitle: "Результат появится здесь", @@ -63,9 +71,15 @@ export const ru: Dict = { recalc: "Пересчёт…", nextTool: "⛓ Следующий инструмент", breakChain: "✂ Оборвать цепочку", + noResult: "результата пока нет", + parts: "частей", + format: "Формат", + alt: "Изображение-результат", }, paramsCard: { noParams: "У этого инструмента нет параметров — результат уже готов.", + configureOutput: "Настроить вывод", + noSchema: "У этого инструмента пока нет схемы.", }, textInput: { heading: "Текст", @@ -79,6 +93,17 @@ export const ru: Dict = { copy: "Копировать", downloadTxt: "Скачать .txt", }, + actions: { + generate: "Сгенерировать", + generating: "Генерация…", + openImage: "Открыть изображение", + downloadResult: "Скачать результат", + }, + textSource: { + placeholder: "Вставьте base64 / hex / байты…", + trySample: "Попробовать образец", + render: "Отрисовать текст", + }, download: { busy: "Готовим файл…", file: "Скачать .{ext}", @@ -93,6 +118,8 @@ export const ru: Dict = { dropZone: { pickDefault: "Перетащите изображение сюда или нажмите, чтобы выбрать файл", overlayDefault: "Отпустите файл, чтобы заменить изображение", + pickTitle: "Перетащите PNG сюда", + pickHint: "или нажмите, чтобы выбрать — всё локально", }, search: { placeholder: "Найдите инструмент…", @@ -110,6 +137,25 @@ export const ru: Dict = { overlayTitle: "Знак", overlayDrop: "Перетащите PNG-знак или нажмите", overlayRemove: "Убрать знак", + autoUpdate: "обновляется автоматически", + width: "Ширина", + height: "Высота", + from: "От", + to: "До", + font: "Шрифт", + size: "Размер", + color: "Цвет", + bold: "Жирный", + fontSans: "Без засечек", + fontSerif: "С засечками", + fontMono: "Моноширинный", + opacity: "Непрозрачность", + angle: "Угол", + backingPlate: "Подложка", + addColor: "+ Добавить цвет", + removeColor: "Удалить цвет", + themeToggle: "Переключить тему", + language: "Язык", }, errors: { noImageRun: "Этот инструмент не обрабатывает изображения", @@ -152,29 +198,11 @@ export const ru: Dict = { cropSize: "Ширина и высота области обрезки должны быть положительными", sizePositive: "Размеры должны быть положительными и конечными", tooManyParts: "Слишком много частей ({count}). Ограничение — 1000.", + toolUnknown: "Инструмента с id «{id}» нет в реестре.", }, + fields: {}, + groups: {}, tools: { - "jpg-to-png": { - title: "Конвертировать JPG в PNG", - description: - "Открывает JPEG и сохраняет его как PNG без потерь. Прозрачность, если была, сохраняется.", - }, - "webp-to-png": { - title: "Конвертировать WebP в PNG", - description: "Перекодирует WebP-изображение в универсальный PNG.", - }, - "gif-to-png": { - title: "Конвертировать GIF в PNG", - description: "Достаёт первый кадр GIF-анимации и сохраняет его как PNG.", - }, - "bmp-to-png": { - title: "Конвертировать BMP в PNG", - description: "Перекодирует BMP в компактный PNG без потерь.", - }, - "ico-to-png": { - title: "Конвертировать ICO в PNG", - description: "Превращает иконку .ico в обычный PNG нужного размера.", - }, "png-to-bmp": { title: "Конвертировать PNG в BMP", description: @@ -288,6 +316,11 @@ export const ru: Dict = { "Повторяет изображение сеткой из выбранного числа столбцов и строк.", params: { columns: "Столбцов", rows: "Строк" }, }, + "split-into-parts-png": { + title: "Разрезать PNG на части", + description: + "Делит изображение на сетку одинаковых по размеру частей. Холст дополняется прозрачностью, чтобы каждая часть была одного размера.", + }, "center-by-alpha-png": { title: "Центрировать PNG по содержимому", description: @@ -358,6 +391,36 @@ export const ru: Dict = { }, }, }, + cmyk: { + title: "Конвертировать PNG в цвета CMYK", + description: + "Раскладывает изображение на печатные компоненты Cyan, Magenta, Yellow и Key (чёрный).", + }, + hsl: { + title: "Разбить PNG на HSL", + description: + "Раскладывает изображение на компоненты тона, насыщенности и светлоты.", + }, + hsi: { + title: "Разбить PNG на HSI", + description: + "Раскладывает изображение на компоненты тона, насыщенности и интенсивности.", + }, + hsv: { + title: "Разбить PNG на HSV", + description: + "Раскладывает изображение на компоненты тона, насыщенности и значения (яркости).", + }, + lab: { + title: "Конвертировать PNG в цвета LAB", + description: + "Раскладывает изображение на перцепционную светлоту и оппонентные пары зелёный–пурпур / синий–жёлтый.", + }, + ycbcr: { + title: "Конвертировать PNG в цвета YCbCr", + description: + "Раскладывает изображение на яркость (Y) и цветоразностные компоненты Cb / Cr.", + }, "black-and-white-png": { title: "Чёрно-белый PNG по порогу", description: @@ -477,11 +540,6 @@ export const ru: Dict = { tolerance: "Порог похожести, %", }, }, - "png-info": { - title: "Информация о PNG", - description: - "Показывает размеры, наличие альфа-канала и количество уникальных цветов загруженного изображения.", - }, "create-empty-png": { title: "Создать пустой PNG", description: @@ -642,83 +700,6 @@ export const ru: Dict = { grayscaleNo: "Нет — найдены цветные пиксели.", }, }, - "png-to-hsl": { - title: "Разложить PNG в HSL", - description: - "Раскладывает изображение на компоненты Тон, Насыщенность и Светлота.", - params: { component: "Компонент", display: "Режим показа" }, - options: { - component: { h: "Тон (H)", s: "Насыщенность (S)", l: "Светлота (L)" }, - display: { gray: "Градациями серого", color: "Пространство как RGB" }, - }, - }, - "png-to-hsv": { - title: "Разложить PNG в HSV", - description: - "Раскладывает изображение на Тон, Насыщенность и Яркость (Value).", - params: { component: "Компонент", display: "Режим показа" }, - options: { - component: { h: "Тон (H)", s: "Насыщенность (S)", v: "Яркость (V)" }, - display: { gray: "Градациями серого", color: "Пространство как RGB" }, - }, - }, - "png-to-hsi": { - title: "Разложить PNG в HSI", - description: - "Раскладывает изображение на Тон, Насыщенность и Интенсивность.", - params: { component: "Компонент", display: "Режим показа" }, - options: { - component: { - h: "Тон (H)", - s: "Насыщенность (S)", - i: "Интенсивность (I)", - }, - display: { gray: "Градациями серого", color: "Пространство как RGB" }, - }, - }, - "png-to-cmyk": { - title: "PNG в CMYK-цвета", - description: - "Раскладывает изображение на печатные компоненты: Голубой, Пурпурный, Жёлтый и Чёрный (Key).", - params: { component: "Компонент", display: "Режим показа" }, - options: { - component: { - c: "Голубой (C)", - m: "Пурпурный (M)", - y: "Жёлтый (Y)", - k: "Чёрный (K)", - }, - display: { gray: "Градациями серого", color: "Пространство как RGB" }, - }, - }, - "png-to-ycbcr": { - title: "PNG в YCbCr-цвета", - description: - "Раскладывает изображение на Яркость (Y) и цветоразностные компоненты Cb / Cr.", - params: { component: "Компонент", display: "Режим показа" }, - options: { - component: { - y: "Яркость (Y)", - cb: "Синий-разностный (Cb)", - cr: "Красный-разностный (Cr)", - }, - display: { gray: "Градациями серого", color: "Пространство как RGB" }, - }, - }, - "png-to-lab": { - title: "PNG в LAB-цвета", - description: - "Раскладывает изображение на perceptual-компоненты: Светлость, зелёный–пурпурный и синий–жёлтый.", - params: { component: "Компонент", display: "Режим показа" }, - options: { - component: { - l: "Светлость (L)", - a: "Зелёный–пурпурный (a)", - b: "Синий–жёлтый (b)", - }, - display: { gray: "Градациями серого", color: "Пространство как RGB" }, - }, - }, "circle-mask-png": { title: "Круглая маска PNG", description: @@ -1024,29 +1005,6 @@ export const ru: Dict = { pattern: { "floyd-steinberg": "Флойд–Стейнберг", bayer: "Байер 4×4" }, }, }, - "compress-png": { - title: "Сжать PNG", - description: - "Уменьшает размер PNG сокращением палитры до выбранного уровня. Честный компромисс: меньше цветов — меньше файл.", - params: { level: "Уровень сжатия" }, - options: { - level: { - light: "Лёгкий (192 цвета)", - balanced: "Сбалансированный (96 цветов)", - strong: "Сильный (44 цвета)", - extreme: "Экстремальный (16 цветов)", - }, - }, - }, - "reduce-to-size-png": { - title: "Вписать PNG в размер", - description: - "Бинарным поиском подбирает размер палитры, чтобы закодированный PNG уложился в целевое количество КБ. Если не влезает даже при 2 цветах — вернёт двухцветный вариант.", - params: { - targetKB: "Целевой размер, КБ", - maxColors: "Максимум цветов для перебора", - }, - }, "png-file-size": { title: "Размер файла PNG", description: @@ -1168,30 +1126,6 @@ export const ru: Dict = { }, }, }, - "watermark-image-png": { - title: "Знак картинкой PNG", - description: - "Накладывает другой PNG (логотип, подпись): масштаб от ширины холста, прозрачность, позиция 3×3. Знак живёт, пока открыта страница, — после восстановления цепочки выберите его заново.", - params: { - scale: "Ширина знака, % от холста", - opacity: "Непрозрачность, %", - position: "Позиция", - margin: "Отступ, px", - }, - options: { - position: { - "top-left": "Сверху слева", - "top-center": "Сверху по центру", - "top-right": "Сверху справа", - "middle-left": "По центру слева", - center: "По центру", - "middle-right": "По центру справа", - "bottom-left": "Снизу слева", - "bottom-center": "Снизу по центру", - "bottom-right": "Снизу справа", - }, - }, - }, "add-text-png": { title: "Надпись на PNG", description: