chore(i18n): refresh uk translations

This commit is contained in:
openclaw-docs-i18n[bot] 2026-04-25 01:41:02 +00:00
parent 2689782a41
commit f4a9e453f3

View File

@ -0,0 +1,327 @@
---
x-i18n:
generated_at: "2026-04-25T01:40:02Z"
model: gpt-5.4
provider: openai
source_hash: cccaaa1b3e472279b7548ad5af5d50162db9e99a731e06be796de64ee9f8c8d8
source_path: superpowers/specs/2026-04-22-tweakcn-custom-theme-import-design.md
workflow: 15
---
# Дизайн імпорту користувацької теми Tweakcn
Статус: схвалено в терміналі 2026-04-22
## Підсумок
Додати рівно один браузерно-локальний слот користувацької теми Control UI, який можна імпортувати з посилання поширення tweakcn. Наявні вбудовані сімейства тем залишаються `claw`, `knot` і `dash`. Нове сімейство `custom` поводиться як звичайне сімейство тем OpenClaw і підтримує режими `light`, `dark` і `system`, коли імпортований payload tweakcn містить обидва набори токенів — для світлого й темного режимів.
Імпортована тема зберігається лише в поточному профілі браузера разом з іншими налаштуваннями Control UI. Вона не записується в конфігурацію Gateway і не синхронізується між пристроями чи браузерами.
## Проблема
Система тем Control UI зараз замкнена на трьох жорстко закодованих сімействах тем:
- `ui/src/ui/theme.ts`
- `ui/src/ui/views/config.ts`
- `ui/src/styles/base.css`
Користувачі можуть перемикатися між вбудованими сімействами та варіантами режимів, але не можуть додати тему з tweakcn без редагування CSS у репозиторії. Потрібний результат менший за загальну систему тем: зберегти три вбудовані теми й додати один керований користувачем імпортований слот, який можна замінювати через посилання tweakcn.
## Цілі
- Зберегти наявні вбудовані сімейства тем без змін.
- Додати рівно один імпортований користувацький слот, а не бібліотеку тем.
- Приймати посилання поширення tweakcn або прямий URL `https://tweakcn.com/r/themes/{id}`.
- Зберігати імпортовану тему лише в локальному сховищі браузера.
- Зробити так, щоб імпортований слот працював з наявними елементами керування режимами `light`, `dark` і `system`.
- Зберегти безпечну поведінку при помилках: невдалий імпорт ніколи не повинен ламати активну тему UI.
## Не цілі
- Жодної бібліотеки з багатьох тем або браузерно-локального списку імпортів.
- Жодного збереження на боці Gateway або синхронізації між пристроями.
- Жодного довільного редактора CSS або редактора сирого JSON теми.
- Жодного автоматичного завантаження віддалених шрифтів з tweakcn.
- Жодних спроб підтримати payload tweakcn, які надають лише один режим.
- Жодного рефакторингу тем у межах усього репозиторію, окрім швів, потрібних для Control UI.
## Уже ухвалені рішення користувача
- Зберегти три вбудовані теми.
- Додати один слот імпорту на базі tweakcn.
- Зберігати імпортовану тему в браузері, а не в конфігурації Gateway.
- Підтримувати `light`, `dark` і `system` для імпортованого слота.
- Перезаписування користувацького слота наступним імпортом є очікуваною поведінкою.
## Рекомендований підхід
Додати четвертий ідентифікатор сімейства тем, `custom`, до моделі теми Control UI. Сімейство `custom` стає доступним для вибору лише тоді, коли присутній валідний імпорт tweakcn. Імпортований payload нормалізується в запис користувацької теми, специфічний для OpenClaw, і зберігається в локальному сховищі браузера разом з іншими налаштуваннями UI.
Під час виконання OpenClaw рендерить керований тег `<style>`, який визначає розв’язані блоки користувацьких CSS-змінних:
```css
:root[data-theme="custom"] { ... }
:root[data-theme="custom-light"] { ... }
```
Це дозволяє ізолювати змінні користувацької теми в межах сімейства `custom` і не дає вбудованим сімействам успадковувати інлайнові CSS-змінні.
## Архітектура
### Модель теми
Оновити `ui/src/ui/theme.ts`:
- Розширити `ThemeName`, додавши `custom`.
- Розширити `ResolvedTheme`, додавши `custom` і `custom-light`.
- Розширити `VALID_THEME_NAMES`.
- Оновити `resolveTheme()`, щоб `custom` віддзеркалювала наявну поведінку сімейств:
- `custom + dark` -> `custom`
- `custom + light` -> `custom-light`
- `custom + system` -> `custom` або `custom-light` залежно від уподобань ОС
Для `custom` не додаються жодні застарілі псевдоніми.
### Модель збереження
Розширити збереження `UiSettings` у `ui/src/ui/storage.ts`, додавши один необов’язковий payload користувацької теми:
- `customTheme?: ImportedCustomTheme`
Рекомендована форма збережених даних:
```ts
type ImportedCustomTheme = {
sourceUrl: string;
themeId: string;
label: string;
importedAt: string;
light: Record<string, string>;
dark: Record<string, string>;
};
```
Примітки:
- `sourceUrl` зберігає початкове введення користувача після нормалізації.
- `themeId` — це ідентифікатор теми tweakcn, витягнутий з URL.
- `label` — це поле tweakcn `name`, якщо воно присутнє, інакше `Custom`.
- `light` і `dark` — це вже нормалізовані мапи токенів OpenClaw, а не сирі payload tweakcn.
- Імпортований payload зберігається поруч з іншими браузерно-локальними налаштуваннями й серіалізується в тому самому документі локального сховища.
- Якщо під час завантаження збережені дані користувацької теми відсутні або невалідні, ігнорувати payload і повертатися до `theme: "claw"`, якщо збереженим сімейством було `custom`.
### Застосування під час виконання
Додати вузький менеджер стилів користувацької теми в runtime Control UI, поруч із `ui/src/ui/app-settings.ts` і `ui/src/ui/theme.ts`.
Обов’язки:
- Створювати або оновлювати один стабільний тег `<style id="openclaw-custom-theme">` у `document.head`.
- Генерувати CSS лише тоді, коли присутній валідний payload користувацької теми.
- Видаляти вміст тега стилю, коли payload очищено.
- Залишити CSS вбудованих сімейств у `ui/src/styles/base.css`; не вставляти імпортовані токени до відстежуваного в репозиторії стилю.
Цей менеджер запускається щоразу, коли налаштування завантажуються, зберігаються, імпортуються або очищуються.
### Селектори світлого режиму
Реалізація має віддавати перевагу `data-theme-mode="light"` для стилізації світлого режиму між усіма сімействами, замість спеціальної обробки `custom-light`. Якщо наявний селектор прив’язаний до `data-theme="light"` і має застосовуватися до кожного світлого сімейства, розширити його в межах цієї роботи.
## UX імпорту
Оновити `ui/src/ui/views/config.ts` у розділі `Appearance`:
- Додати картку теми `Custom` поруч із `Claw`, `Knot` і `Dash`.
- Показувати картку як вимкнену, якщо імпортованої користувацької теми немає.
- Додати панель імпорту під сіткою тем із такими елементами:
- одне текстове поле для посилання поширення tweakcn або URL `/r/themes/{id}`
- одна кнопка `Import`
- один шлях `Replace`, якщо payload `custom` уже існує
- одна дія `Clear`, якщо payload `custom` уже існує
- Показувати мітку імпортованої теми та хост джерела, якщо payload існує.
- Якщо активною темою є `custom`, імпорт заміни застосовується негайно.
- Якщо активною темою не є `custom`, імпорт лише зберігає новий payload, доки користувач не вибере картку `Custom`.
Швидкий вибір теми в `ui/src/ui/views/config-quick.ts` також має показувати `Custom` лише тоді, коли payload існує.
## Розбір URL і віддалене отримання
Шлях імпорту в браузері приймає:
- `https://tweakcn.com/themes/{id}`
- `https://tweakcn.com/r/themes/{id}`
Реалізація має нормалізувати обидві форми до:
- `https://tweakcn.com/r/themes/{id}`
Потім браузер напряму виконує запит до нормалізованого endpoint `/r/themes/{id}`.
Використовувати вузький валідатор схеми для зовнішнього payload. Бажано застосувати zod, оскільки це недовірена зовнішня межа.
Обов’язкові поля віддалених даних:
- верхньорівневе `name` як необов’язковий рядок
- `cssVars.theme` як необов’язковий об’єкт
- `cssVars.light` як об’єкт
- `cssVars.dark` як об’єкт
Якщо відсутній `cssVars.light` або `cssVars.dark`, відхилити імпорт. Це зроблено навмисно: затверджена продуктова поведінка — повна підтримка режимів, а не найкраща можлива синтезація відсутньої сторони.
## Мапування токенів
Не віддзеркалювати змінні tweakcn безрозбірно. Нормалізувати обмежену підмножину до токенів OpenClaw, а решту виводити в допоміжній функції.
### Токени, що імпортуються напряму
З кожного блоку режиму tweakcn:
- `background`
- `foreground`
- `card`
- `card-foreground`
- `popover`
- `popover-foreground`
- `primary`
- `primary-foreground`
- `secondary`
- `secondary-foreground`
- `muted`
- `muted-foreground`
- `accent`
- `accent-foreground`
- `destructive`
- `destructive-foreground`
- `border`
- `input`
- `ring`
- `radius`
Із спільного `cssVars.theme`, якщо воно присутнє:
- `font-sans`
- `font-mono`
Якщо блок режиму перевизначає `font-sans`, `font-mono` або `radius`, значення локального режиму має пріоритет.
### Токени, що виводяться для OpenClaw
Імпортер виводить змінні, специфічні для OpenClaw, з імпортованих базових кольорів:
- `--bg-accent`
- `--bg-elevated`
- `--bg-hover`
- `--panel`
- `--panel-strong`
- `--panel-hover`
- `--chrome`
- `--chrome-strong`
- `--text`
- `--text-strong`
- `--chat-text`
- `--muted`
- `--muted-strong`
- `--accent-hover`
- `--accent-muted`
- `--accent-subtle`
- `--accent-glow`
- `--focus`
- `--focus-ring`
- `--focus-glow`
- `--secondary`
- `--secondary-foreground`
- `--danger`
- `--danger-muted`
- `--danger-subtle`
Правила виведення живуть у чистій допоміжній функції, щоб їх можна було тестувати окремо. Точні формули змішування кольорів — це деталь реалізації, але допоміжна функція має задовольняти дві умови:
- зберігати читабельний контраст, близький до задуму імпортованої теми
- давати стабільний результат для одного й того самого імпортованого payload
### Токени, які ігноруються у v1
Ці токени tweakcn навмисно ігноруються в першій версії:
- `chart-*`
- `sidebar-*`
- `font-serif`
- `shadow-*`
- `tracking-*`
- `letter-spacing`
- `spacing`
Це дозволяє зосередити обсяг робіт на токенах, які поточний Control UI справді використовує.
### Шрифти
Рядки стеків шрифтів імпортуються, якщо вони присутні, але OpenClaw не завантажує віддалені ресурси шрифтів у v1. Якщо імпортований стек посилається на шрифти, які недоступні в браузері, застосовується звичайна поведінка fallback.
## Поведінка при помилках
Невдалі імпорти мають завершуватися безпечно.
- Невалідний формат URL: показати вбудовану помилку валідації, не виконувати запит.
- Непідтримуваний хост або форма шляху: показати вбудовану помилку валідації, не виконувати запит.
- Збій мережі, відповідь не-OK або некоректний JSON: показати вбудовану помилку, не змінювати поточний збережений payload.
- Збій схеми або відсутність блоків light/dark: показати вбудовану помилку, не змінювати поточний збережений payload.
- Дія очищення:
- видаляє збережений payload користувацької теми
- видаляє вміст керованого тега стилю користувацької теми
- якщо `custom` активна, перемикає сімейство тем назад на `claw`
- Невалідний збережений payload користувацької теми при першому завантаженні:
- ігнорувати збережений payload
- не генерувати користувацький CSS
- якщо збереженим сімейством тем було `custom`, повертатися до `claw`
За жодних обставин невдалий імпорт не повинен залишати активний документ із частково застосованими змінними користувацького CSS.
## Файли, які, ймовірно, зміняться під час реалізації
Основні файли:
- `ui/src/ui/theme.ts`
- `ui/src/ui/storage.ts`
- `ui/src/ui/app-settings.ts`
- `ui/src/ui/views/config.ts`
- `ui/src/ui/views/config-quick.ts`
- `ui/src/styles/base.css`
Імовірні нові допоміжні файли:
- `ui/src/ui/custom-theme.ts`
- `ui/src/ui/custom-theme-import.ts`
Тести:
- `ui/src/ui/app-settings.test.ts`
- `ui/src/ui/storage.node.test.ts`
- `ui/src/ui/views/config.browser.test.ts`
- нові сфокусовані тести для розбору URL і нормалізації payload
## Тестування
Мінімальне покриття реалізації:
- розібрати URL посилання поширення в ідентифікатор теми tweakcn
- нормалізувати `/themes/{id}` і `/r/themes/{id}` до URL отримання
- відхиляти непідтримувані хости та некоректні ідентифікатори
- валідувати форму payload tweakcn
- мапити валідний payload tweakcn у нормалізовані мапи токенів OpenClaw для світлого й темного режимів
- завантажувати та зберігати payload користувацької теми в браузерно-локальних налаштуваннях
- розв’язувати `custom` для `light`, `dark` і `system`
- вимикати вибір `Custom`, коли payload відсутній
- застосовувати імпортовану тему негайно, коли `custom` уже активна
- повертатися до `claw`, коли активну користувацьку тему очищено
Ціль ручної перевірки:
- імпортувати відому тему tweakcn із Settings
- перемикатися між `light`, `dark` і `system`
- перемикатися між `custom` і вбудованими сімействами
- перезавантажити сторінку та підтвердити, що імпортована користувацька тема зберігається локально
## Нотатки щодо розгортання
Ця функція навмисно невелика. Якщо користувачі згодом попросять кілька імпортованих тем, перейменування, експорт або синхронізацію між пристроями, розглядати це як наступний дизайн. Не закладати наперед абстракцію бібліотеки тем у цій реалізації.