From edae76acca70d3d7935d85585f56ce8a6b587b1f Mon Sep 17 00:00:00 2001 From: Ars Golushkov Date: Sat, 25 Jul 2026 18:11:02 +0300 Subject: [PATCH 1/3] =?UTF-8?q?test(web):=20red=20spec=20for=20issue=20#26?= =?UTF-8?q?86=20=E2=80=94=20daemon's=20raw=20English=20error=20shown=20in?= =?UTF-8?q?=20zh-CN?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A failing test in DesignSystemsSection.test.tsx anchors the bug: when the daemon rejects a design-system import (e.g. BAD_REQUEST from a local path check), the Settings form renders the raw `result.error.message` (English) directly in the Chinese UI. The fix will route the error envelope through a localized formatter (formatDesignSystemImportError) that maps `code` → i18n key and keeps the raw detail under a
disclosure. Refs #2686. --- .../components/DesignSystemsSection.test.tsx | 68 ++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/apps/web/tests/components/DesignSystemsSection.test.tsx b/apps/web/tests/components/DesignSystemsSection.test.tsx index d87491814e4..f6d23941611 100644 --- a/apps/web/tests/components/DesignSystemsSection.test.tsx +++ b/apps/web/tests/components/DesignSystemsSection.test.tsx @@ -8,7 +8,12 @@ import { afterEach, describe, expect, it, vi } from 'vitest'; import type { DesignSystemSummary } from '@open-design/contracts'; import { DesignSystemsSection } from '../../src/components/DesignSystemsSection'; -import { fetchDesignSystems, updateDesignSystemDraft } from '../../src/providers/registry'; +import { I18nProvider } from '../../src/i18n'; +import { + fetchDesignSystems, + importLocalDesignSystem, + updateDesignSystemDraft, +} from '../../src/providers/registry'; import type { AppConfig } from '../../src/types'; const memoryCss = readFileSync(resolve(process.cwd(), 'src/styles/viewer/memory.css'), 'utf8'); @@ -63,6 +68,11 @@ vi.mock('../../src/providers/registry', async () => { ...actual, fetchDesignSystems: vi.fn(async () => [editable, builtIn]), updateDesignSystemDraft: vi.fn(async () => ({ ...editable, title: 'Acme v2', body: '' })), + // Default to a successful response so unrelated tests don't hit the real fetch. + // Individual tests override with `mockResolvedValueOnce` to assert error paths. + importLocalDesignSystem: vi.fn( + async () => ({ designSystem: editable }) as Awaited>, + ), }; }); @@ -199,3 +209,59 @@ describe('DesignSystemsSection rename (issue #2811)', () => { } }); }); + +// Issue #2686: when the daemon rejects a design-system import, the Settings +// form must not surface its raw English message in a non-English UI. Today +// the import-error slot renders `result.error.message` directly, so a Chinese +// (or any other non-English) locale sees an English error inline. The red +// spec anchors the contract: after a failed import, the daemon's English +// text must not be visible in the rendered form. The fix will route the +// error envelope through a localized formatter (`formatDesignSystemImportError`) +// that maps `code` to an i18n key and keeps the raw detail under a details +// disclosure. +describe('DesignSystemsSection import error localization (issue #2686)', () => { + it('does not surface the daemon raw English message in the import form under zh-CN', async () => { + vi.mocked(importLocalDesignSystem).mockResolvedValueOnce({ + error: { + code: 'BAD_REQUEST', + message: 'local project path must be a directory', + }, + }); + + render( + + {}} /> + , + ); + + // Open the import form (collapsible +Add design system panel). + const addButton = await screen.findByRole('button', { + name: /add design system|添加设计系统/i, + }); + fireEvent.click(addButton); + + // Fill in the local-import path field. + const pathInput = await screen.findByPlaceholderText(/\/path\/to\/project/); + fireEvent.change(pathInput, { target: { value: '/tmp/non-existent' } }); + + // Submit. The button text is localized ("从项目导入" in zh-CN) — match on a unique substring. + const submit = screen.getByRole('button', { + name: /从项目导入/i, + }); + fireEvent.click(submit); + + // Sanity: the import client was actually invoked with our typed path. + await waitFor(() => { + expect(importLocalDesignSystem).toHaveBeenCalledWith( + expect.objectContaining({ baseDir: '/tmp/non-existent' }), + ); + }); + + // The daemon's English error must NOT be rendered to the user. + await waitFor(() => { + expect( + screen.queryByText(/local project path must be a directory/i), + ).toBeNull(); + }); + }); +}); From 8cf143496d8d828ec156a710a98a8a78a3dfd445 Mon Sep 17 00:00:00 2001 From: Ars Golushkov Date: Sat, 25 Jul 2026 19:01:50 +0300 Subject: [PATCH 2/3] fix(web): localize design-system import errors (#2686) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The daemon returns English error messages for design-system import failures, and the Settings form rendered them raw — so every non-English locale saw English text in an otherwise localized UI. The fix routes the error envelope through `designSystemImportErrorKey`, which maps `code` (`BAD_REQUEST` / `INTERNAL_ERROR`) to a new i18n key. The localized summary replaces the raw English as the user-facing message, while the raw daemon detail (paths, URLs) remains accessible under a
disclosure for diagnostics. - New runtime helper: `apps/web/src/runtime/design-system-import-error.ts` - 3 new i18n keys across all 19 locales - Component change: `DesignSystemsSection.tsx` stores the full error envelope (with `code`) instead of just the message string - Red spec: `DesignSystemsSection.test.tsx` proves the raw English is no longer the primary visible text in zh-CN - Unit tests for the code-to-key mapping Fixes #2686 --- .../src/components/DesignSystemsSection.tsx | 18 ++++++++++-- apps/web/src/i18n/locales/ar.ts | 3 ++ apps/web/src/i18n/locales/de.ts | 3 ++ apps/web/src/i18n/locales/en.ts | 3 ++ apps/web/src/i18n/locales/es-ES.ts | 3 ++ apps/web/src/i18n/locales/fa.ts | 3 ++ apps/web/src/i18n/locales/fr.ts | 3 ++ apps/web/src/i18n/locales/hu.ts | 3 ++ apps/web/src/i18n/locales/id.ts | 3 ++ apps/web/src/i18n/locales/it.ts | 3 ++ apps/web/src/i18n/locales/ja.ts | 3 ++ apps/web/src/i18n/locales/ko.ts | 3 ++ apps/web/src/i18n/locales/pl.ts | 3 ++ apps/web/src/i18n/locales/pt-BR.ts | 3 ++ apps/web/src/i18n/locales/ru.ts | 3 ++ apps/web/src/i18n/locales/th.ts | 3 ++ apps/web/src/i18n/locales/tr.ts | 3 ++ apps/web/src/i18n/locales/uk.ts | 3 ++ apps/web/src/i18n/locales/zh-CN.ts | 3 ++ apps/web/src/i18n/locales/zh-TW.ts | 3 ++ apps/web/src/i18n/types.ts | 3 ++ .../src/runtime/design-system-import-error.ts | 18 ++++++++++++ .../components/DesignSystemsSection.test.tsx | 12 +++++--- .../design-system-import-error.test.ts | 29 +++++++++++++++++++ 24 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 apps/web/src/runtime/design-system-import-error.ts create mode 100644 apps/web/tests/runtime/design-system-import-error.test.ts diff --git a/apps/web/src/components/DesignSystemsSection.tsx b/apps/web/src/components/DesignSystemsSection.tsx index 5de3dae9a76..2ab4065b654 100644 --- a/apps/web/src/components/DesignSystemsSection.tsx +++ b/apps/web/src/components/DesignSystemsSection.tsx @@ -2,6 +2,7 @@ import { Dialog, DialogFooter, DialogTitle } from '@open-design/components'; import { useEffect, useId, useMemo, useRef, useState } from 'react'; import type { Dispatch, FormEvent, SetStateAction } from 'react'; import { useT } from '../i18n'; +import { designSystemImportErrorKey } from '../runtime/design-system-import-error'; import type { AppConfig, DesignSystemGenerationJob, DesignSystemSummary } from '../types'; import { fetchDesignSystems, @@ -9,6 +10,7 @@ import { importLocalDesignSystem, importShadcnDesignSystem, updateDesignSystemDraft, + type SkillImportError, } from '../providers/registry'; import { DesignSystemPreviewModal } from './DesignSystemPreviewModal'; import { Icon } from './Icon'; @@ -71,7 +73,7 @@ export function DesignSystemsSection({ const [importMessage, setImportMessage] = useState(null); const [importedDesignSystem, setImportedDesignSystem] = useState(null); const [highlightedDesignSystemId, setHighlightedDesignSystemId] = useState(null); - const [importError, setImportError] = useState(null); + const [importError, setImportError] = useState(null); useEffect(() => { fetchDesignSystems().then(setDesignSystems); @@ -239,7 +241,7 @@ export function DesignSystemsSection({ : await importLocalDesignSystem({ baseDir: importTarget, ...importOptions }); setImporting(false); if ('error' in result) { - setImportError(result.error.message); + setImportError(result.error); return; } setDesignSystems((current) => { @@ -276,6 +278,8 @@ export function DesignSystemsSection({ }); } + const importErrorKey = importError ? designSystemImportErrorKey(importError) : null; + return (
@@ -451,7 +455,15 @@ export function DesignSystemsSection({
- {importError ?

{importError}

: null} + {importError ? ( +

+ {importErrorKey ? t(importErrorKey) : importError.message} +

+ {t('settings.designSystemsImportErrorDetails')} + {importError.message} +
+

+ ) : null} {importMessage ? (

{t('settings.designSystemsImportedStatus', { title: importMessage })} diff --git a/apps/web/src/i18n/locales/ar.ts b/apps/web/src/i18n/locales/ar.ts index e515125b6bb..bc215be6c55 100644 --- a/apps/web/src/i18n/locales/ar.ts +++ b/apps/web/src/i18n/locales/ar.ts @@ -3457,6 +3457,9 @@ export const ar: Dict = { 'settings.designSystemsImportProject': 'استيراد من المشروع', 'settings.designSystemsImportedStatus': 'تم استيراد {title}', 'settings.designSystemsViewImported': 'عرض نظام التصميم المستورد', + 'settings.designSystemsImportErrorInvalid': 'تعذر استيراد نظام التصميم. تحقق من المسار أو عنوان URL وحاول مرة أخرى.', + 'settings.designSystemsImportErrorInternal': 'تعذر استيراد نظام التصميم بسبب خطأ داخلي. حاول مرة أخرى.', + 'settings.designSystemsImportErrorDetails': 'التفاصيل', 'settings.designSystemsCategory': 'الفئة', 'settings.designSystemsAllCategories': 'كل الفئات', 'settings.designSystemsShowInHomeGallery': 'إظهار في معرض الصفحة الرئيسية', diff --git a/apps/web/src/i18n/locales/de.ts b/apps/web/src/i18n/locales/de.ts index 3e8d67401b9..145dff73f8c 100644 --- a/apps/web/src/i18n/locales/de.ts +++ b/apps/web/src/i18n/locales/de.ts @@ -3457,6 +3457,9 @@ export const de: Dict = { 'settings.designSystemsImportProject': 'Aus Projekt importieren', 'settings.designSystemsImportedStatus': '{title} importiert', 'settings.designSystemsViewImported': 'Importiertes Design-System anzeigen', + 'settings.designSystemsImportErrorInvalid': 'Design-System konnte nicht importiert werden. Überprüfen Sie den Pfad oder die URL und versuchen Sie es erneut.', + 'settings.designSystemsImportErrorInternal': 'Das Design-System konnte aufgrund eines internen Fehlers nicht importiert werden. Bitte versuchen Sie es erneut.', + 'settings.designSystemsImportErrorDetails': 'Details', 'settings.designSystemsCategory': 'Kategorie', 'settings.designSystemsAllCategories': 'Alle Kategorien', 'settings.designSystemsShowInHomeGallery': 'In Home-Galerie anzeigen', diff --git a/apps/web/src/i18n/locales/en.ts b/apps/web/src/i18n/locales/en.ts index ecf80e793ec..11f3d01d4e7 100644 --- a/apps/web/src/i18n/locales/en.ts +++ b/apps/web/src/i18n/locales/en.ts @@ -3495,6 +3495,9 @@ export const en: Dict = { 'settings.designSystemsImportProject': 'Import from project', 'settings.designSystemsImportedStatus': 'Imported {title}', 'settings.designSystemsViewImported': 'View imported design system', + 'settings.designSystemsImportErrorInvalid': 'Couldn\'t import design system. Check the path or URL and try again.', + 'settings.designSystemsImportErrorInternal': 'Couldn\'t import design system due to an internal error. Please try again.', + 'settings.designSystemsImportErrorDetails': 'Details', 'settings.designSystemsCategory': 'Category', 'settings.designSystemsAllCategories': 'All categories', 'settings.designSystemsShowInHomeGallery': 'Show in home gallery', diff --git a/apps/web/src/i18n/locales/es-ES.ts b/apps/web/src/i18n/locales/es-ES.ts index e12a6ad4f60..c13cbf9c3b0 100644 --- a/apps/web/src/i18n/locales/es-ES.ts +++ b/apps/web/src/i18n/locales/es-ES.ts @@ -3457,6 +3457,9 @@ export const esES: Dict = { 'settings.designSystemsImportProject': 'Importar desde proyecto', 'settings.designSystemsImportedStatus': '{title} importado', 'settings.designSystemsViewImported': 'Ver sistema de diseño importado', + 'settings.designSystemsImportErrorInvalid': 'No se pudo importar el sistema de diseño. Compruebe la ruta o la URL e inténtelo de nuevo.', + 'settings.designSystemsImportErrorInternal': 'No se pudo importar el sistema de diseño debido a un error interno. Inténtelo de nuevo.', + 'settings.designSystemsImportErrorDetails': 'Detalles', 'settings.designSystemsCategory': 'Categoría', 'settings.designSystemsAllCategories': 'Todas las categorías', 'settings.designSystemsShowInHomeGallery': 'Mostrar en la galería de inicio', diff --git a/apps/web/src/i18n/locales/fa.ts b/apps/web/src/i18n/locales/fa.ts index d9f14d3a238..474e3a08a9e 100644 --- a/apps/web/src/i18n/locales/fa.ts +++ b/apps/web/src/i18n/locales/fa.ts @@ -3457,6 +3457,9 @@ export const fa: Dict = { 'settings.designSystemsImportProject': 'درون‌ریزی از پروژه', 'settings.designSystemsImportedStatus': '{title} درون‌ریزی شد', 'settings.designSystemsViewImported': 'مشاهده سیستم طراحی درون‌ریزی‌شده', + 'settings.designSystemsImportErrorInvalid': 'سیستم طراحی وارد نشد. مسیر یا URL را بررسی کرده و دوباره امتحان کنید.', + 'settings.designSystemsImportErrorInternal': 'به دلیل خطای داخلی، سیستم طراحی وارد نشد. لطفاً دوباره امتحان کنید.', + 'settings.designSystemsImportErrorDetails': 'جزئیات', 'settings.designSystemsCategory': 'دسته‌بندی', 'settings.designSystemsAllCategories': 'همه دسته‌بندی‌ها', 'settings.designSystemsShowInHomeGallery': 'نمایش در گالری خانه', diff --git a/apps/web/src/i18n/locales/fr.ts b/apps/web/src/i18n/locales/fr.ts index 5c119f8ead5..8a1b745037f 100644 --- a/apps/web/src/i18n/locales/fr.ts +++ b/apps/web/src/i18n/locales/fr.ts @@ -3457,6 +3457,9 @@ export const fr: Dict = { 'settings.designSystemsImportProject': 'Importer depuis le projet', 'settings.designSystemsImportedStatus': '{title} importé', 'settings.designSystemsViewImported': 'Voir le système de design importé', + 'settings.designSystemsImportErrorInvalid': 'Impossible d’importer le design system. Vérifiez le chemin ou l’URL et réessayez.', + 'settings.designSystemsImportErrorInternal': 'Impossible d’importer le design system en raison d’une erreur interne. Veuillez réessayer.', + 'settings.designSystemsImportErrorDetails': 'Détails', 'settings.designSystemsCategory': 'Catégorie', 'settings.designSystemsAllCategories': 'Toutes les catégories', 'settings.designSystemsShowInHomeGallery': 'Afficher dans la galerie d’accueil', diff --git a/apps/web/src/i18n/locales/hu.ts b/apps/web/src/i18n/locales/hu.ts index 9bfefbcbcde..1633346700a 100644 --- a/apps/web/src/i18n/locales/hu.ts +++ b/apps/web/src/i18n/locales/hu.ts @@ -3457,6 +3457,9 @@ export const hu: Dict = { 'settings.designSystemsImportProject': 'Importálás projektből', 'settings.designSystemsImportedStatus': '{title} importálva', 'settings.designSystemsViewImported': 'Importált designrendszer megtekintése', + 'settings.designSystemsImportErrorInvalid': 'A designrendszer importálása nem sikerült. Ellenőrizze az elérési utat vagy az URL-t, és próbálja újra.', + 'settings.designSystemsImportErrorInternal': 'A designrendszer importálása belső hiba miatt nem sikerült. Kérjük, próbálja újra.', + 'settings.designSystemsImportErrorDetails': 'Részletek', 'settings.designSystemsCategory': 'Kategória', 'settings.designSystemsAllCategories': 'Minden kategória', 'settings.designSystemsShowInHomeGallery': 'Megjelenítés a kezdő galériában', diff --git a/apps/web/src/i18n/locales/id.ts b/apps/web/src/i18n/locales/id.ts index f03c426b29c..5aa1c0e998b 100644 --- a/apps/web/src/i18n/locales/id.ts +++ b/apps/web/src/i18n/locales/id.ts @@ -3457,6 +3457,9 @@ export const id: Dict = { 'settings.designSystemsImportProject': 'Impor dari proyek', 'settings.designSystemsImportedStatus': '{title} diimpor', 'settings.designSystemsViewImported': 'Lihat sistem desain yang diimpor', + 'settings.designSystemsImportErrorInvalid': 'Tidak dapat mengimpor sistem desain. Periksa jalur atau URL dan coba lagi.', + 'settings.designSystemsImportErrorInternal': 'Tidak dapat mengimpor sistem desain karena kesalahan internal. Silakan coba lagi.', + 'settings.designSystemsImportErrorDetails': 'Detail', 'settings.designSystemsCategory': 'Kategori', 'settings.designSystemsAllCategories': 'Semua kategori', 'settings.designSystemsShowInHomeGallery': 'Tampilkan di galeri beranda', diff --git a/apps/web/src/i18n/locales/it.ts b/apps/web/src/i18n/locales/it.ts index a88bcc97d5c..15eaab3de3a 100644 --- a/apps/web/src/i18n/locales/it.ts +++ b/apps/web/src/i18n/locales/it.ts @@ -3457,6 +3457,9 @@ export const it: Dict = { 'settings.designSystemsImportProject': 'Importa dal progetto', 'settings.designSystemsImportedStatus': '{title} importato', 'settings.designSystemsViewImported': 'Vedi design system importato', + 'settings.designSystemsImportErrorInvalid': 'Impossibile importare il design system. Controlla il percorso o l’URL e riprova.', + 'settings.designSystemsImportErrorInternal': 'Impossibile importare il design system a causa di un errore interno. Riprova.', + 'settings.designSystemsImportErrorDetails': 'Dettagli', 'settings.designSystemsCategory': 'Categoria', 'settings.designSystemsAllCategories': 'Tutte le categorie', 'settings.designSystemsShowInHomeGallery': 'Mostra nella galleria iniziale', diff --git a/apps/web/src/i18n/locales/ja.ts b/apps/web/src/i18n/locales/ja.ts index a51d0dc2a87..00177f85010 100644 --- a/apps/web/src/i18n/locales/ja.ts +++ b/apps/web/src/i18n/locales/ja.ts @@ -3457,6 +3457,9 @@ export const ja: Dict = { 'settings.designSystemsImportProject': 'プロジェクトからインポート', 'settings.designSystemsImportedStatus': '{title} をインポートしました', 'settings.designSystemsViewImported': 'インポートしたデザインシステムを表示', + 'settings.designSystemsImportErrorInvalid': 'デザインシステムをインポートできませんでした。パスまたはURLを確認して、もう一度お試しください。', + 'settings.designSystemsImportErrorInternal': '内部エラーのため、デザインシステムをインポートできませんでした。もう一度お試しください。', + 'settings.designSystemsImportErrorDetails': '詳細', 'settings.designSystemsCategory': 'カテゴリー', 'settings.designSystemsAllCategories': 'すべてのカテゴリー', 'settings.designSystemsShowInHomeGallery': 'ホームギャラリーに表示', diff --git a/apps/web/src/i18n/locales/ko.ts b/apps/web/src/i18n/locales/ko.ts index 08976356967..0623223cb55 100644 --- a/apps/web/src/i18n/locales/ko.ts +++ b/apps/web/src/i18n/locales/ko.ts @@ -3457,6 +3457,9 @@ export const ko: Dict = { 'settings.designSystemsImportProject': '프로젝트에서 가져오기', 'settings.designSystemsImportedStatus': '{title} 가져옴', 'settings.designSystemsViewImported': '가져온 디자인 시스템 보기', + 'settings.designSystemsImportErrorInvalid': '디자인 시스템을 가져올 수 없습니다. 경로 또는 URL을 확인하고 다시 시도하세요.', + 'settings.designSystemsImportErrorInternal': '낸부 오류로 인해 디자인 시스템을 가져올 수 없습니다. 다시 시도하세요.', + 'settings.designSystemsImportErrorDetails': '세부 정보', 'settings.designSystemsCategory': '카테고리', 'settings.designSystemsAllCategories': '모든 카테고리', 'settings.designSystemsShowInHomeGallery': '홈 갤러리에 표시', diff --git a/apps/web/src/i18n/locales/pl.ts b/apps/web/src/i18n/locales/pl.ts index 5681a715b3a..cf27571b380 100644 --- a/apps/web/src/i18n/locales/pl.ts +++ b/apps/web/src/i18n/locales/pl.ts @@ -3457,6 +3457,9 @@ export const pl: Dict = { 'settings.designSystemsImportProject': 'Importuj z projektu', 'settings.designSystemsImportedStatus': 'Zaimportowano {title}', 'settings.designSystemsViewImported': 'Pokaż zaimportowany system projektowy', + 'settings.designSystemsImportErrorInvalid': 'Nie można zaimportować systemu projektowego. Sprawdź ścieżkę lub adres URL i spróbuj ponownie.', + 'settings.designSystemsImportErrorInternal': 'Nie można zaimportować systemu projektowego z powodu błędu wewnętrznego. Spróbuj ponownie.', + 'settings.designSystemsImportErrorDetails': 'Szczegóły', 'settings.designSystemsCategory': 'Kategoria', 'settings.designSystemsAllCategories': 'Wszystkie kategorie', 'settings.designSystemsShowInHomeGallery': 'Pokaż w galerii głównej', diff --git a/apps/web/src/i18n/locales/pt-BR.ts b/apps/web/src/i18n/locales/pt-BR.ts index e9e288020c9..b0995f5cef1 100644 --- a/apps/web/src/i18n/locales/pt-BR.ts +++ b/apps/web/src/i18n/locales/pt-BR.ts @@ -3457,6 +3457,9 @@ export const ptBR: Dict = { 'settings.designSystemsImportProject': 'Importar do projeto', 'settings.designSystemsImportedStatus': '{title} importado', 'settings.designSystemsViewImported': 'Ver design system importado', + 'settings.designSystemsImportErrorInvalid': 'Não foi possível importar o design system. Verifique o caminho ou a URL e tente novamente.', + 'settings.designSystemsImportErrorInternal': 'Não foi possível importar o design system devido a um erro interno. Tente novamente.', + 'settings.designSystemsImportErrorDetails': 'Detalhes', 'settings.designSystemsCategory': 'Categoria', 'settings.designSystemsAllCategories': 'Todas as categorias', 'settings.designSystemsShowInHomeGallery': 'Mostrar na galeria inicial', diff --git a/apps/web/src/i18n/locales/ru.ts b/apps/web/src/i18n/locales/ru.ts index c73e8e2ca68..1619c3ad347 100644 --- a/apps/web/src/i18n/locales/ru.ts +++ b/apps/web/src/i18n/locales/ru.ts @@ -3457,6 +3457,9 @@ export const ru: Dict = { 'settings.designSystemsImportProject': 'Импортировать из проекта', 'settings.designSystemsImportedStatus': 'Импортировано: {title}', 'settings.designSystemsViewImported': 'Открыть импортированную дизайн-систему', + 'settings.designSystemsImportErrorInvalid': 'Не удалось импортировать дизайн-систему. Проверьте путь или URL и попробуйте снова.', + 'settings.designSystemsImportErrorInternal': 'Не удалось импортировать дизайн-систему из-за внутренней ошибки. Попробуйте снова.', + 'settings.designSystemsImportErrorDetails': 'Подробности', 'settings.designSystemsCategory': 'Категория', 'settings.designSystemsAllCategories': 'Все категории', 'settings.designSystemsShowInHomeGallery': 'Показывать в домашней галерее', diff --git a/apps/web/src/i18n/locales/th.ts b/apps/web/src/i18n/locales/th.ts index fbe4c86211d..e2c9594e814 100644 --- a/apps/web/src/i18n/locales/th.ts +++ b/apps/web/src/i18n/locales/th.ts @@ -3457,6 +3457,9 @@ export const th: Dict = { 'settings.designSystemsImportProject': 'นำเข้าจากโปรเจกต์', 'settings.designSystemsImportedStatus': 'นำเข้า {title} แล้ว', 'settings.designSystemsViewImported': 'ดูระบบออกแบบที่นำเข้า', + 'settings.designSystemsImportErrorInvalid': 'ไม่สามารถนำเข้าระบบออกแบบได้ ตรวจสอบเส้นทางหรือ URL แล้วลองอีกครั้ง', + 'settings.designSystemsImportErrorInternal': 'ไม่สามารถนำเข้าระบบออกแบบได้เนื่องจากข้อผิดพลาดภายใน โปรดลองอีกครั้ง', + 'settings.designSystemsImportErrorDetails': 'รายละเอียด', 'settings.designSystemsCategory': 'หมวดหมู่', 'settings.designSystemsAllCategories': 'ทุกหมวดหมู่', 'settings.designSystemsShowInHomeGallery': 'แสดงในแกลเลอรีหน้าแรก', diff --git a/apps/web/src/i18n/locales/tr.ts b/apps/web/src/i18n/locales/tr.ts index d7043be9a75..027bf1c4c3f 100644 --- a/apps/web/src/i18n/locales/tr.ts +++ b/apps/web/src/i18n/locales/tr.ts @@ -3457,6 +3457,9 @@ export const tr: Dict = { 'settings.designSystemsImportProject': 'Projeden içe aktar', 'settings.designSystemsImportedStatus': '{title} içe aktarıldı', 'settings.designSystemsViewImported': 'İçe aktarılan tasarım sistemini görüntüle', + 'settings.designSystemsImportErrorInvalid': 'Tasarım sistemi içe aktarılamadı. Yolu veya URL\'yi kontrol edip tekrar deneyin.', + 'settings.designSystemsImportErrorInternal': 'Dahili bir hata nedeniyle tasarım sistemi içe aktarılamadı. Lütfen tekrar deneyin.', + 'settings.designSystemsImportErrorDetails': 'Ayrıntılar', 'settings.designSystemsCategory': 'Kategori', 'settings.designSystemsAllCategories': 'Tüm kategoriler', 'settings.designSystemsShowInHomeGallery': 'Ana galeride göster', diff --git a/apps/web/src/i18n/locales/uk.ts b/apps/web/src/i18n/locales/uk.ts index d54e12390d3..b940f6e9e64 100644 --- a/apps/web/src/i18n/locales/uk.ts +++ b/apps/web/src/i18n/locales/uk.ts @@ -3457,6 +3457,9 @@ export const uk: Dict = { 'settings.designSystemsImportProject': 'Імпортувати з проєкту', 'settings.designSystemsImportedStatus': 'Імпортовано {title}', 'settings.designSystemsViewImported': 'Переглянути імпортовану дизайн-систему', + 'settings.designSystemsImportErrorInvalid': 'Не вдалося імпортувати дизайн-систему. Перевірте шлях або URL і спробуйте ще раз.', + 'settings.designSystemsImportErrorInternal': 'Не вдалося імпортувати дизайн-систему через внутрішню помилку. Спробуйте ще раз.', + 'settings.designSystemsImportErrorDetails': 'Деталі', 'settings.designSystemsCategory': 'Категорія', 'settings.designSystemsAllCategories': 'Усі категорії', 'settings.designSystemsShowInHomeGallery': 'Показувати в домашній галереї', diff --git a/apps/web/src/i18n/locales/zh-CN.ts b/apps/web/src/i18n/locales/zh-CN.ts index 106876d98a8..eaecde1e6ca 100644 --- a/apps/web/src/i18n/locales/zh-CN.ts +++ b/apps/web/src/i18n/locales/zh-CN.ts @@ -3709,6 +3709,9 @@ export const zhCN: Dict = { "settings.designSystemsImportProject": "从项目导入", "settings.designSystemsImportedStatus": "已导入 {title}", "settings.designSystemsViewImported": "查看导入的设计系统", + "settings.designSystemsImportErrorInvalid": "无法导入设计系统。请检查路径或 URL 后重试。", + "settings.designSystemsImportErrorInternal": "由于内部错误,无法导入设计系统。请重试。", + "settings.designSystemsImportErrorDetails": "详细信息", "settings.designSystemsCategory": "分类", "settings.designSystemsAllCategories": "所有分类", "settings.designSystemsShowInHomeGallery": "在首页 Gallery 中显示", diff --git a/apps/web/src/i18n/locales/zh-TW.ts b/apps/web/src/i18n/locales/zh-TW.ts index a6ba478185b..1e49389b93e 100644 --- a/apps/web/src/i18n/locales/zh-TW.ts +++ b/apps/web/src/i18n/locales/zh-TW.ts @@ -3718,6 +3718,9 @@ export const zhTW: Dict = { "settings.designSystemsImportProject": "從專案匯入", "settings.designSystemsImportedStatus": "已匯入 {title}", "settings.designSystemsViewImported": "查看匯入的設計系統", + "settings.designSystemsImportErrorInvalid": "無法匯入設計系統。請檢查路徑或 URL 後重試。", + "settings.designSystemsImportErrorInternal": "由於內部錯誤,無法匯入設計系統。請重試。", + "settings.designSystemsImportErrorDetails": "詳細資訊", "settings.designSystemsCategory": "分類", "settings.designSystemsAllCategories": "所有分類", "settings.designSystemsShowInHomeGallery": "在首頁 Gallery 中顯示", diff --git a/apps/web/src/i18n/types.ts b/apps/web/src/i18n/types.ts index e751a1c5239..92e2a3cda88 100644 --- a/apps/web/src/i18n/types.ts +++ b/apps/web/src/i18n/types.ts @@ -603,6 +603,9 @@ export interface Dict { 'settings.designSystemsImportProject': string; 'settings.designSystemsImportedStatus': string; 'settings.designSystemsViewImported': string; + 'settings.designSystemsImportErrorInvalid': string; + 'settings.designSystemsImportErrorInternal': string; + 'settings.designSystemsImportErrorDetails': string; 'settings.designSystemsCategory': string; 'settings.designSystemsAllCategories': string; 'settings.designSystemsShowInHomeGallery': string; diff --git a/apps/web/src/runtime/design-system-import-error.ts b/apps/web/src/runtime/design-system-import-error.ts new file mode 100644 index 00000000000..c00a36111ed --- /dev/null +++ b/apps/web/src/runtime/design-system-import-error.ts @@ -0,0 +1,18 @@ +/** + * Maps a daemon design-system-import error code to its i18n key. + * + * The daemon returns `{ error: { code, message } }` where `message` is + * always English. This helper lets the UI show a localized summary for + * known codes while keeping the raw detail (paths, URLs) under a + *

disclosure. + * + * Returns `null` for unknown or missing codes — the caller should fall + * back to the raw `error.message` (pre-#2686 behavior). + */ +export function designSystemImportErrorKey( + error: { code?: string }, +): 'settings.designSystemsImportErrorInvalid' | 'settings.designSystemsImportErrorInternal' | null { + if (error.code === 'INTERNAL_ERROR') return 'settings.designSystemsImportErrorInternal'; + if (error.code === 'BAD_REQUEST') return 'settings.designSystemsImportErrorInvalid'; + return null; +} diff --git a/apps/web/tests/components/DesignSystemsSection.test.tsx b/apps/web/tests/components/DesignSystemsSection.test.tsx index f6d23941611..ce924fa3579 100644 --- a/apps/web/tests/components/DesignSystemsSection.test.tsx +++ b/apps/web/tests/components/DesignSystemsSection.test.tsx @@ -257,11 +257,15 @@ describe('DesignSystemsSection import error localization (issue #2686)', () => { ); }); - // The daemon's English error must NOT be rendered to the user. + // The localized Chinese summary replaces the raw English as the + // user-facing message. The raw detail stays under
. await waitFor(() => { - expect( - screen.queryByText(/local project path must be a directory/i), - ).toBeNull(); + expect(screen.getByText(/无法导入设计系统/)).toBeInTheDocument(); }); + + // Raw daemon detail is still accessible for diagnostics. + const detail = document.querySelector('.library-install-error-detail code'); + expect(detail).toBeTruthy(); + expect(detail!.textContent).toBe('local project path must be a directory'); }); }); diff --git a/apps/web/tests/runtime/design-system-import-error.test.ts b/apps/web/tests/runtime/design-system-import-error.test.ts new file mode 100644 index 00000000000..96b16ebf860 --- /dev/null +++ b/apps/web/tests/runtime/design-system-import-error.test.ts @@ -0,0 +1,29 @@ +import { describe, expect, it } from 'vitest'; + +import { designSystemImportErrorKey } from '../../src/runtime/design-system-import-error'; + +describe('designSystemImportErrorKey', () => { + it('maps BAD_REQUEST to the invalid-import key', () => { + expect(designSystemImportErrorKey({ code: 'BAD_REQUEST' })).toBe( + 'settings.designSystemsImportErrorInvalid', + ); + }); + + it('maps INTERNAL_ERROR to the internal-error key', () => { + expect(designSystemImportErrorKey({ code: 'INTERNAL_ERROR' })).toBe( + 'settings.designSystemsImportErrorInternal', + ); + }); + + it('returns null for unknown codes', () => { + expect(designSystemImportErrorKey({ code: 'SOMETHING_ELSE' })).toBeNull(); + }); + + it('returns null when code is missing', () => { + expect(designSystemImportErrorKey({})).toBeNull(); + }); + + it('returns null for an empty code string', () => { + expect(designSystemImportErrorKey({ code: '' })).toBeNull(); + }); +}); From 5c666d7a7b385c64155d487a41a0173a43c411a0 Mon Sep 17 00:00:00 2001 From: Ars Golushkov Date: Sun, 2 Aug 2026 15:01:04 +0300 Subject: [PATCH 3/3] =?UTF-8?q?fix(web):=20address=20review=20=E2=80=94=20?= =?UTF-8?q?fix=20HTML=20nesting=20and=20Korean=20typo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace

wrapper with

around import error block to avoid invalid
nesting inside

- Fix Korean internal error message: 낸부 → 낸부 (U+B0B8 → U+B0B4) --- apps/web/src/components/DesignSystemsSection.tsx | 6 +++--- apps/web/src/i18n/locales/ko.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/web/src/components/DesignSystemsSection.tsx b/apps/web/src/components/DesignSystemsSection.tsx index 2ab4065b654..76cb3989c6a 100644 --- a/apps/web/src/components/DesignSystemsSection.tsx +++ b/apps/web/src/components/DesignSystemsSection.tsx @@ -456,13 +456,13 @@ export function DesignSystemsSection({

{importError ? ( -

- {importErrorKey ? t(importErrorKey) : importError.message} +

+

{importErrorKey ? t(importErrorKey) : importError.message}

{t('settings.designSystemsImportErrorDetails')} {importError.message}
-

+
) : null} {importMessage ? (

diff --git a/apps/web/src/i18n/locales/ko.ts b/apps/web/src/i18n/locales/ko.ts index 0623223cb55..b523266eb01 100644 --- a/apps/web/src/i18n/locales/ko.ts +++ b/apps/web/src/i18n/locales/ko.ts @@ -3458,7 +3458,7 @@ export const ko: Dict = { 'settings.designSystemsImportedStatus': '{title} 가져옴', 'settings.designSystemsViewImported': '가져온 디자인 시스템 보기', 'settings.designSystemsImportErrorInvalid': '디자인 시스템을 가져올 수 없습니다. 경로 또는 URL을 확인하고 다시 시도하세요.', - 'settings.designSystemsImportErrorInternal': '낸부 오류로 인해 디자인 시스템을 가져올 수 없습니다. 다시 시도하세요.', + 'settings.designSystemsImportErrorInternal': '내부 오류로 인해 디자인 시스템을 가져올 수 없습니다. 다시 시도하세요.', 'settings.designSystemsImportErrorDetails': '세부 정보', 'settings.designSystemsCategory': '카테고리', 'settings.designSystemsAllCategories': '모든 카테고리',