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
+6 -2
View File
@@ -1,6 +1,7 @@
import { error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types.js';
import * as boardService from '$lib/server/services/boardService.js';
import * as appService from '$lib/server/services/appService.js';
import * as permissionService from '$lib/server/services/permissionService.js';
import { EntityType, PermissionLevel, UserRole } from '$lib/utils/constants.js';
import { isBoardGuestAccessible } from '$lib/server/middleware/guestAccess.js';
@@ -32,7 +33,10 @@ export const load: PageServerLoad = async ({ params, locals }) => {
try {
// findBoardById includes sections -> widgets -> app -> statuses
const board = await boardService.findBoardById(boardId);
const [board, allApps] = await Promise.all([
boardService.findBoardById(boardId),
appService.findAll()
]);
// Determine if user can edit this board
let canEdit = false;
@@ -50,7 +54,7 @@ export const load: PageServerLoad = async ({ params, locals }) => {
}
}
return { board, canEdit };
return { board, canEdit, allApps };
} catch (err) {
const message = err instanceof Error ? err.message : 'Board not found';
if (message.includes('not found')) {