feat(phase2): localization EN/RU + additional widget types

- Add svelte-i18n with 224 translation keys (English + Russian)
- Language switcher in header (EN/RU toggle, persists to localStorage)
- Extract all hardcoded strings from 37 component/page files
- Add 4 new widget types: Bookmark, Note (markdown), Embed (iframe), Status
- WidgetRenderer dispatches by type, WidgetGrid supports full-width widgets
- Type-specific config forms in board editor
- Install marked for markdown rendering
This commit is contained in:
2026-03-24 23:18:05 +03:00
parent bf4e5089ee
commit 477c0e4d52
52 changed files with 1776 additions and 395 deletions
+29
View File
@@ -123,6 +123,35 @@ export const updateSectionSchema = z.object({
isExpandedByDefault: z.boolean().optional()
});
// --- Widget Config Schemas ---
export const appWidgetConfigSchema = z.object({
appId: z.string().min(1, 'App ID is required')
});
export const bookmarkWidgetConfigSchema = z.object({
url: z.string().url('Invalid URL'),
label: z.string().min(1, 'Label is required').max(200),
icon: z.string().max(100).optional(),
description: z.string().max(500).optional()
});
export const noteWidgetConfigSchema = z.object({
content: z.string().max(10000, 'Content too long'),
format: z.enum(['markdown', 'text']).default('markdown')
});
export const embedWidgetConfigSchema = z.object({
url: z.string().url('Invalid URL'),
height: z.number().int().min(100).max(2000).default(300),
sandbox: z.string().max(200).optional()
});
export const statusWidgetConfigSchema = z.object({
appIds: z.array(z.string().min(1)).min(1, 'At least one app is required'),
label: z.string().max(200).optional()
});
// --- Widget ---
export const createWidgetSchema = z.object({