fix: update i18n - schema components

This commit is contained in:
2026-09-13 06:21:28 +05:00
parent a4c85c0814
commit 6c88a23e48
14 changed files with 86 additions and 64 deletions
+3 -2
View File
@@ -1,8 +1,9 @@
# План: инструмент «Разрезать PNG на части» (split-into-parts-png) # План: инструмент «Разрезать PNG на части» (split-into-parts-png)
> Статус: **выполнено и в архиве** (2026-09). Инструмент и механизм «результат = > Статус: **выполнено и в архиве** (2026-09). Инструмент и механизм «результат =
> набор файлов» (1 → many) реализованы; первый потребитель — `split-into-parts-png`. > набор файлов» (1 → many) реализованы; первый потребитель —
> Общий процесс таких инструментов — задача 18 в `docs/backlog.md`. > `split-into-parts-png`. Общий процесс таких инструментов — задача 18 в
> `docs/backlog.md`.
## Цель ## Цель
+18 -31
View File
@@ -156,12 +156,11 @@
- `verdictTone(key)``success`|`danger`|`info` по имени ключа - `verdictTone(key)``success`|`danger`|`info` по имени ключа
(`*Yes`/`*No`/`*Portrait`/`*Landscape`) — не по строке. (`*Yes`/`*No`/`*Portrait`/`*Landscape`) — не по строке.
- **0.9** Расширить тип `Dict` (только новая ветка `lib/i18n`): - **0.9** Расширить тип `Dict` (только новая ветка `lib/i18n`):
- секция `preview` **не заводится**: оставшиеся после чистки mono-лейблов (см. - секция `preview` **не заводится**: строки нового UI живут в собственных
решение B) строки нового UI живут в собственных категориях — расширяем категориях — расширяем существующие (`catalog`, `header`, `dropZone`,
существующие (`catalog`, `header`, `dropZone`, `sourceCard`, `resultCard`, `sourceCard`, `resultCard`, `paramsCard`, `textResult`, `ui`) и заводим две
`paramsCard`, `textResult`, `ui`) и заводим две маленькие новые: `actions` маленькие новые: `actions` (Generate / Open image / Download result…) и
(Generate / Open image / Download result…) и `textSource` (placeholder, Try `textSource` (placeholder, Try sample…);
sample…);
- новая глобальная секция `fields: Record<string, string>` — переводы подписей - новая глобальная секция `fields: Record<string, string>` — переводы подписей
полей по ключу из схемы (решение C); полей по ключу из схемы (решение C);
- новая глобальная секция `groups: Record<string, string>` — переводы - новая глобальная секция `groups: Record<string, string>` — переводы
@@ -197,36 +196,29 @@
`t("header.footerNote")`. `t("header.footerNote")`.
- **3.3** `tools/[id]/+page.svelte`: «Tool not found», fallback title → `t()`. - **3.3** `tools/[id]/+page.svelte`: «Tool not found», fallback title → `t()`.
### Фаза 4: Компоненты — основной блок (по одному коммиту на компонент) ### Фаза 4: Компоненты — основной блок (коммиты кучками по смыслу)
Каждый коммит: удаление декоративных mono-лейблов (решение B) + замена Все текстовые подписи в компонентах — информативные, сохраняем и переводим на
оставшихся строк на `t`/хелперы + lint/check. Список mono-лейблов, которые `t`/хелперы. Каждый коммит: замена строк + lint/check.
**удаляем**: eyebrow'ы (`PNG PROCESSING / SINGLE TOOL`, `KIT SHOWCASE`,
`EASY-PNG-TOOLS / CATALOG`), статусы (`LIVE PREVIEW`, `rendering ok`), панельные
подписи (`TOOL SETTINGS`), дублирующие капшены (`SOURCE / RESULT`,
`GENERATOR / RESULT`). Оставляем и локализуем только информативные: категории
каталога, счётчики инструментов, подписи данных (`FORMAT`, `parts`, `px`, «ZIP
(PNG)»), alt-тексты, а также содержательные заголовки («Configure output»).
- `SchemaToolView.svelte`: убрать eyebrow/`LIVE PREVIEW`/`TOOL SETTINGS`, - `SchemaToolView.svelte`: title/description →
перевести «Configure output» и «This tool has no schema yet.». `toolTitle()`/`toolDescription()`, перевести `TOOL SETTINGS`, «Configure
- `SchemaSourceTile.svelte`: убрать figcaption `SOURCE`, перевести «choose an output» и «This tool has no schema yet.».
- `SchemaSourceTile.svelte`: перевести figcaption `SOURCE`, «choose an
image»/«no source…» и alt. image»/«no source…» и alt.
- `SchemaResultTile.svelte`: убрать figcaption `RESULT`, перевести «no result - `SchemaResultTile.svelte`: перевести figcaption `RESULT`, «no result yet» и
yet»/«parts» и alt. alt; суффикс «parts» — в `PreviewTile`.
- `SchemaPreview.svelte`: убрать панельные - `SchemaPreview.svelte`: перевести панельный лейбл `PREVIEW PANEL` и
`SOURCE / RESULT`/`GENERATOR / RESULT`, перевести meta-капшены (`FORMAT` и meta-капшены `SOURCE / RESULT / FORMAT`; значения «parts»/«text» → `t()`.
т.п.).
- `SchemaActions.svelte`: Generating…, Generate, Open image, Download result. - `SchemaActions.svelte`: Generating…, Generate, Open image, Download result.
- `SchemaFields.svelte`: Reset, «updates automatically», `labelOf(field.id)` - `SchemaFields.svelte`: Reset, «updates automatically», `labelOf(field.id)`
`fieldLabel(field)`. `fieldLabel(field)`.
- `SchemaTextSource.svelte`: placeholder, Try sample, Render text. - `SchemaTextSource.svelte`: placeholder, Try sample, Render text.
- `SchemaTextResult.svelte`: убрать лейбл `RESULT` у вердикта, перевести Copy / - `SchemaTextResult.svelte`: перевести лейбл `RESULT` у вердикта, Copy /
Download .txt; tone detection → `verdictTone()`. Download .txt; tone detection → `verdictTone()`.
- `CatalogToolbar.svelte`: фильтры → `t("categories.all")` + - `CatalogToolbar.svelte`: фильтры → `t("categories.all")` +
`t("categories.X")`, поисковый placeholder. `t("categories.X")`, поисковый placeholder.
- `CatalogHeader.svelte`: убрать eyebrow, перевести heading/lead и счётчик - `CatalogHeader.svelte`: перевести heading/lead и счётчик «TOOLS AVAILABLE».
«TOOLS AVAILABLE».
- `CatalogGroup.svelte`: перевести суффикс счётчика «TOOLS». - `CatalogGroup.svelte`: перевести суффикс счётчика «TOOLS».
- `Dropzone.svelte`: текст зоны → `t("dropZone.pickDefault")`. - `Dropzone.svelte`: текст зоны → `t("dropZone.pickDefault")`.
- Schema field controls (по одному или группой): Width/Height, From/To, Backing - Schema field controls (по одному или группой): Width/Height, From/To, Backing
@@ -320,11 +312,6 @@
(`title: "groups.canvas"`), перевод — в глобальной секции `groups` словаря (`title: "groups.canvas"`), перевод — в глобальной секции `groups` словаря
(`Dict.groups: Record<string, string>`). В UI — `groupLabel(title)` = (`Dict.groups: Record<string, string>`). В UI — `groupLabel(title)` =
`t(title)` с фолбэком на сырой ключ. `t(title)` с фолбэком на сырой ключ.
- **B. Mono-лейблы**: декоративные лейблы без полезной информации **удаляем**
(eyebrow'ы, статусы, панельные капшены, дублирующие подписи секций) — они
занимают место. Оставляем только там, где реально нужно, и локализуем:
счётчики инструментов, категории каталога, подписи данных (FORMAT, parts, px,
«ZIP (PNG)»), alt-тексты, содержательные headings.
- **C. Лейблы полей**: в схеме задаём i18n-ключ - **C. Лейблы полей**: в схеме задаём i18n-ключ
(`field.number({ label: "fields.thickness", … })`), в UI выводится перевод — (`field.number({ label: "fields.thickness", … })`), в UI выводится перевод —
`fieldLabel(field)` = `t(label)`. Ключи — глобальная секция `fields` словаря, `fieldLabel(field)` = `t(label)`. Ключи — глобальная секция `fields` словаря,
+6 -1
View File
@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { Copy } from "@lucide/svelte"; import { Copy } from "@lucide/svelte";
import { t } from "$lib/i18n/t";
import IconButton from "./ui/IconButton.svelte"; import IconButton from "./ui/IconButton.svelte";
interface Props { interface Props {
@@ -16,7 +17,11 @@
<pre class="code-pre"><code>{code}</code></pre> <pre class="code-pre"><code>{code}</code></pre>
{#if copyable} {#if copyable}
<div class="code-copy"> <div class="code-copy">
<IconButton icon={Copy} label="Copy" onclick={() => oncopy?.()} /> <IconButton
icon={Copy}
label={t("textResult.copy")}
onclick={() => oncopy?.()}
/>
</div> </div>
{/if} {/if}
</div> </div>
+4 -2
View File
@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { Upload } from "@lucide/svelte"; import { Upload } from "@lucide/svelte";
import { t } from "$lib/i18n/t";
import DownloadButton from "./ui/DownloadButton.svelte"; import DownloadButton from "./ui/DownloadButton.svelte";
interface Props { interface Props {
@@ -16,7 +17,8 @@
<div class="actions"> <div class="actions">
{#if inputMode === "image"} {#if inputMode === "image"}
<label class="btn upload"> <label class="btn upload">
<Upload size={14} /> Open image <Upload size={14} />
{t("actions.openImage")}
<input <input
type="file" type="file"
accept="image/*" accept="image/*"
@@ -29,7 +31,7 @@
{/if} {/if}
{#if canDownload} {#if canDownload}
<DownloadButton <DownloadButton
label="Download result" label={t("actions.downloadResult")}
onclick={ondownload} onclick={ondownload}
disabled={running} disabled={running}
/> />
+9 -7
View File
@@ -4,6 +4,7 @@
import SchemaResultTile from "$lib/components/SchemaResultTile.svelte"; import SchemaResultTile from "$lib/components/SchemaResultTile.svelte";
import SchemaSourceTile from "$lib/components/SchemaSourceTile.svelte"; import SchemaSourceTile from "$lib/components/SchemaSourceTile.svelte";
import type { PixelImage } from "$lib/core/types"; import type { PixelImage } from "$lib/core/types";
import { t } from "$lib/i18n/t";
import type { FileResult, InputMode, ResultKind } from "$lib/registry"; import type { FileResult, InputMode, ResultKind } from "$lib/registry";
interface Props { interface Props {
@@ -46,7 +47,7 @@
case "none": case "none":
return "—"; return "—";
case "text": case "text":
return "text"; return t("textInput.heading");
case "image": case "image":
return source ? `${source.width} × ${source.height} px` : "—"; return source ? `${source.width} × ${source.height} px` : "—";
} }
@@ -58,10 +59,10 @@
: "—" : "—"
: resultKind === "files" : resultKind === "files"
? fileResult ? fileResult
? `${fileResult.files.length} parts` ? `${fileResult.files.length} ${t("resultCard.parts")}`
: "—" : "—"
: textResult : textResult
? "text" ? t("textInput.heading")
: "—", : "—",
); );
const formatValue = $derived(resultKind === "files" ? "ZIP (PNG)" : "PNG"); const formatValue = $derived(resultKind === "files" ? "ZIP (PNG)" : "PNG");
@@ -75,7 +76,7 @@
</script> </script>
<div class="panel-head"> <div class="panel-head">
<span class="label">PREVIEW PANEL</span> <span class="label">{t("resultCard.previewPanel")}</span>
<SchemaActions <SchemaActions
{inputMode} {inputMode}
canDownload={hasResult} canDownload={hasResult}
@@ -112,9 +113,9 @@
<div class="meta"> <div class="meta">
<MetaList <MetaList
items={[ items={[
{ caption: "SOURCE", value: sourceValue }, { caption: t("sourceCard.source"), value: sourceValue },
{ caption: "RESULT", value: resultValue }, { caption: t("resultCard.result"), value: resultValue },
{ caption: "FORMAT", value: formatValue }, { caption: t("resultCard.format"), value: formatValue },
]} ]}
/> />
</div> </div>
@@ -132,6 +133,7 @@
.label { .label {
font: var(--font-size-s) var(--font-mono); font: var(--font-size-s) var(--font-mono);
letter-spacing: var(--space-text-l); letter-spacing: var(--space-text-l);
text-transform: uppercase;
color: var(--color-main); color: var(--color-main);
} }
.error { .error {
@@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import { toDataUrl } from "$lib/core/io"; import { toDataUrl } from "$lib/core/io";
import type { PixelImage } from "$lib/core/types"; import type { PixelImage } from "$lib/core/types";
import { t } from "$lib/i18n/t";
import type { FileResult, ResultKind } from "$lib/registry"; import type { FileResult, ResultKind } from "$lib/registry";
import { Check } from "@lucide/svelte"; import { Check } from "@lucide/svelte";
import SchemaTextResult from "./SchemaTextResult.svelte"; import SchemaTextResult from "./SchemaTextResult.svelte";
@@ -40,7 +41,12 @@
); );
</script> </script>
<PreviewTile label="RESULT" viewMode={resultKind} loading={running} {parts}> <PreviewTile
label={t("resultCard.result")}
viewMode={resultKind}
loading={running}
{parts}
>
<div class="canvas" class:checker={resultKind === "image"}> <div class="canvas" class:checker={resultKind === "image"}>
{#if resultKind === "text" && textResult} {#if resultKind === "text" && textResult}
<div class="text-result-wrap"> <div class="text-result-wrap">
@@ -70,11 +76,11 @@
{/each} {/each}
</div> </div>
{:else if resultKind === "image" && resultUrl} {:else if resultKind === "image" && resultUrl}
<img src={resultUrl} alt="result" /> <img src={resultUrl} alt={t("resultCard.alt")} />
{:else if running} {:else if running}
<Check size={22} /> <Check size={22} />
{:else} {:else}
<span class="empty">no result yet</span> <span class="empty">{t("resultCard.noResult")}</span>
{/if} {/if}
</div> </div>
</PreviewTile> </PreviewTile>
@@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import { toDataUrl } from "$lib/core/io"; import { toDataUrl } from "$lib/core/io";
import type { PixelImage } from "$lib/core/types"; import type { PixelImage } from "$lib/core/types";
import { t } from "$lib/i18n/t";
import type { InputMode } from "$lib/registry"; import type { InputMode } from "$lib/registry";
import PreviewTile from "./layout/PreviewTile.svelte"; import PreviewTile from "./layout/PreviewTile.svelte";
import SchemaTextSource from "./SchemaTextSource.svelte"; import SchemaTextSource from "./SchemaTextSource.svelte";
@@ -25,7 +26,7 @@
const sourceUrl = $derived(source ? toDataUrl(source) : null); const sourceUrl = $derived(source ? toDataUrl(source) : null);
</script> </script>
<PreviewTile label="SOURCE" viewMode={mode}> <PreviewTile label={t("sourceCard.source")} viewMode={mode}>
{#if mode === "text"} {#if mode === "text"}
<div class="text-source-wrap"> <div class="text-source-wrap">
<SchemaTextSource <SchemaTextSource
@@ -36,11 +37,11 @@
/> />
</div> </div>
{:else if mode === "image" && sourceUrl} {:else if mode === "image" && sourceUrl}
<img src={sourceUrl} alt="source" /> <img src={sourceUrl} alt={t("sourceCard.alt")} />
{:else if mode === "image"} {:else if mode === "image"}
<span class="empty">choose an image</span> <span class="empty">{t("sourceCard.chooseImage")}</span>
{:else} {:else}
<span class="empty">no source — configure the parameters</span> <span class="empty">{t("sourceCard.noSource")}</span>
{/if} {/if}
</PreviewTile> </PreviewTile>
@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { Copy, Download, FileText } from "@lucide/svelte"; import { Copy, Download, FileText } from "@lucide/svelte";
import { t } from "$lib/i18n/t";
import IconButton from "./ui/IconButton.svelte"; import IconButton from "./ui/IconButton.svelte";
interface Props { interface Props {
@@ -28,10 +29,10 @@
{#if kind === "verdict"} {#if kind === "verdict"}
<div class="verdict"> <div class="verdict">
<span class="verdict-label">RESULT</span> <span class="verdict-label">{t("resultCard.result")}</span>
<div class="badge badge-tone--{tone}" role="status"> <div class="badge badge-tone--{tone}" role="status">
<span class="verdict-text">{value}</span> <span class="verdict-text">{value}</span>
<IconButton icon={Copy} label="Copy" onclick={oncopy} /> <IconButton icon={Copy} label={t("textResult.copy")} onclick={oncopy} />
</div> </div>
</div> </div>
{:else} {:else}
@@ -39,10 +40,10 @@
<div class="result-head"> <div class="result-head">
<span class="result-label"><FileText size={14} /> {fileName}</span> <span class="result-label"><FileText size={14} /> {fileName}</span>
<div class="result-actions"> <div class="result-actions">
<IconButton icon={Copy} label="Copy" onclick={oncopy} /> <IconButton icon={Copy} label={t("textResult.copy")} onclick={oncopy} />
<IconButton <IconButton
icon={Download} icon={Download}
label="Download .txt" label={t("textResult.downloadTxt")}
onclick={ondownload} onclick={ondownload}
/> />
</div> </div>
@@ -98,6 +99,7 @@
color: var(--color-text-muted); color: var(--color-text-muted);
font: var(--font-size-s) var(--font-mono); font: var(--font-size-s) var(--font-mono);
letter-spacing: var(--space-text-l); letter-spacing: var(--space-text-l);
text-transform: uppercase;
} }
.badge { .badge {
display: inline-flex; display: inline-flex;
@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { ArrowUp, Upload } from "@lucide/svelte"; import { ArrowUp, Upload } from "@lucide/svelte";
import { t } from "$lib/i18n/t";
interface Props { interface Props {
value: string; value: string;
@@ -11,7 +12,7 @@
} }
let { let {
value, value,
placeholder = "Paste base64 / hex / bytes…", placeholder = t("textSource.placeholder"),
disabled = false, disabled = false,
oninput, oninput,
onrender, onrender,
@@ -35,11 +36,13 @@
<div class="actions"> <div class="actions">
{#if onsample} {#if onsample}
<button type="button" class="secondary" onclick={onsample}> <button type="button" class="secondary" onclick={onsample}>
<Upload size={14} /> Try sample <Upload size={14} />
{t("textSource.trySample")}
</button> </button>
{/if} {/if}
<button type="button" class="render" onclick={onrender} {disabled}> <button type="button" class="render" onclick={onrender} {disabled}>
<ArrowUp size={14} /> Render text <ArrowUp size={14} />
{t("textSource.render")}
</button> </button>
</div> </div>
</div> </div>
+7 -5
View File
@@ -6,6 +6,7 @@
import { decodeFile, encode } from "$lib/core/io"; import { decodeFile, encode } from "$lib/core/io";
import type { PixelImage } from "$lib/core/types"; import type { PixelImage } from "$lib/core/types";
import { execute } from "$lib/executor"; import { execute } from "$lib/executor";
import { toolDescription, toolTitle } from "$lib/i18n/schema-tool-strings";
import { t } from "$lib/i18n/t"; import { t } from "$lib/i18n/t";
import type { FileResult, ToolEntry } from "$lib/registry"; import type { FileResult, ToolEntry } from "$lib/registry";
import { import {
@@ -161,16 +162,16 @@
<div class="schema-tool"> <div class="schema-tool">
<header class="header"> <header class="header">
<div class="title-block"> <div class="title-block">
<h1>{tool.title}</h1> <h1>{toolTitle(tool)}</h1>
<p class="lede">{tool.description}</p> <p class="lede">{toolDescription(tool)}</p>
</div> </div>
</header> </header>
<div class="workspace"> <div class="workspace">
<section class="panel settings"> <section class="panel settings">
<div class="panel-head"> <div class="panel-head">
<span class="label">TOOL SETTINGS</span> <span class="label">{t("paramsCard.toolSettings")}</span>
<strong>Configure output</strong> <strong>{t("paramsCard.configureOutput")}</strong>
</div> </div>
<SchemaFields {schema} {values} onchange={setValue} onreset={reset} /> <SchemaFields {schema} {values} onchange={setValue} onreset={reset} />
</section> </section>
@@ -199,7 +200,7 @@
</div> </div>
</div> </div>
{:else} {:else}
<p class="no-schema">This tool has no schema yet.</p> <p class="no-schema">{t("paramsCard.noSchema")}</p>
{/if} {/if}
<style> <style>
@@ -223,6 +224,7 @@
.label { .label {
font: var(--font-size-s) var(--font-mono); font: var(--font-size-s) var(--font-mono);
letter-spacing: var(--space-text-l); letter-spacing: var(--space-text-l);
text-transform: uppercase;
color: var(--color-text-muted); color: var(--color-text-muted);
} }
.label { .label {
+2 -1
View File
@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { Ellipsis, GripVertical, X } from "@lucide/svelte"; import { Ellipsis, GripVertical, X } from "@lucide/svelte";
import { t } from "$lib/i18n/t";
import type { Snippet } from "svelte"; import type { Snippet } from "svelte";
interface Props { interface Props {
@@ -28,7 +29,7 @@
<button <button
type="button" type="button"
class="step-remove" class="step-remove"
aria-label="Remove step" aria-label={t("chain.removeStepAria")}
onclick={() => onremove?.()} onclick={() => onremove?.()}
> >
<X size={16} /> <X size={16} />
@@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import type { InputMode, ResultKind } from "$lib/registry"; import type { InputMode, ResultKind } from "$lib/registry";
import { RefreshCw } from "@lucide/svelte"; import { RefreshCw } from "@lucide/svelte";
import { t } from "$lib/i18n/t";
import type { Snippet } from "svelte"; import type { Snippet } from "svelte";
interface Props { interface Props {
@@ -26,7 +27,7 @@
<span> <span>
{label} {label}
{#if parts !== undefined} {#if parts !== undefined}
<span class="count">{parts} parts</span> <span class="count">{parts} {t("resultCard.parts")}</span>
{/if} {/if}
{#if loading} {#if loading}
<RefreshCw class="rotating" size="12" /> <RefreshCw class="rotating" size="12" />
@@ -45,6 +46,7 @@
gap: var(--space-m); gap: var(--space-m);
margin-bottom: var(--space-m); margin-bottom: var(--space-m);
font: var(--font-size-s) var(--font-mono); font: var(--font-size-s) var(--font-mono);
text-transform: uppercase;
color: var(--color-text-muted); color: var(--color-text-muted);
& :global(.rotating) { & :global(.rotating) {
animation: rotate var(--duration-l) linear infinite; animation: rotate var(--duration-l) linear infinite;
+4
View File
@@ -57,6 +57,7 @@ export const en: Dict = {
removeStepAria: "Remove step", removeStepAria: "Remove step",
}, },
sourceCard: { sourceCard: {
source: "Source",
replaceImage: "Replace image", replaceImage: "Replace image",
chooseImage: "choose an image", chooseImage: "choose an image",
noSource: "no source — configure the parameters", noSource: "no source — configure the parameters",
@@ -71,11 +72,14 @@ export const en: Dict = {
nextTool: "⛓ Next tool", nextTool: "⛓ Next tool",
breakChain: "✂ Break the chain", breakChain: "✂ Break the chain",
noResult: "no result yet", noResult: "no result yet",
result: "Result",
previewPanel: "Preview",
parts: "parts", parts: "parts",
format: "Format", format: "Format",
alt: "Result image", alt: "Result image",
}, },
paramsCard: { paramsCard: {
toolSettings: "Tool settings",
noParams: "This tool has no parameters — the result is ready as is.", noParams: "This tool has no parameters — the result is ready as is.",
configureOutput: "Configure output", configureOutput: "Configure output",
noSchema: "This tool has no schema yet.", noSchema: "This tool has no schema yet.",
+4
View File
@@ -58,6 +58,7 @@ export const ru: Dict = {
removeStepAria: "Убрать шаг", removeStepAria: "Убрать шаг",
}, },
sourceCard: { sourceCard: {
source: "Источник",
replaceImage: "Заменить изображение", replaceImage: "Заменить изображение",
chooseImage: "выберите изображение", chooseImage: "выберите изображение",
noSource: "нет источника — настройте параметры", noSource: "нет источника — настройте параметры",
@@ -72,11 +73,14 @@ export const ru: Dict = {
nextTool: "⛓ Следующий инструмент", nextTool: "⛓ Следующий инструмент",
breakChain: "✂ Оборвать цепочку", breakChain: "✂ Оборвать цепочку",
noResult: "результата пока нет", noResult: "результата пока нет",
result: "Результат",
previewPanel: "Предпросмотр",
parts: "частей", parts: "частей",
format: "Формат", format: "Формат",
alt: "Изображение-результат", alt: "Изображение-результат",
}, },
paramsCard: { paramsCard: {
toolSettings: "Настройки инструмента",
noParams: "У этого инструмента нет параметров — результат уже готов.", noParams: "У этого инструмента нет параметров — результат уже готов.",
configureOutput: "Настроить вывод", configureOutput: "Настроить вывод",
noSchema: "У этого инструмента пока нет схемы.", noSchema: "У этого инструмента пока нет схемы.",