From e97a9283d555606da117ffbf29061ac7990aadf4 Mon Sep 17 00:00:00 2001 From: Anton A S Date: Tue, 3 Mar 2026 12:19:27 +0300 Subject: [PATCH] Fix VitePress i18n: per-locale themeConfig with translated nav/sidebar, typed labels --- packages/docs/.vitepress/config.ts | 184 ++++++++++++++++++----------- 1 file changed, 115 insertions(+), 69 deletions(-) diff --git a/packages/docs/.vitepress/config.ts b/packages/docs/.vitepress/config.ts index 81037a161..1dd78ff60 100644 --- a/packages/docs/.vitepress/config.ts +++ b/packages/docs/.vitepress/config.ts @@ -1,87 +1,110 @@ -import { defineConfig } from 'vitepress' +import { defineConfig, type DefaultTheme } from 'vitepress' -const userGuideSidebar = (prefix = '') => [ +interface SidebarLabels { + gettingAround: string + creatingContent: string + organizing: string + advanced: string + canvasNav: string + selection: string + shapes: string + text: string + pen: string + layers: string + contextMenu: string + exporting: string + autoLayout: string + components: string + variables: string + guide: string + gettingStarted: string + features: string + architecture: string + techStack: string + comparison: string + figmaMatrix: string +} + +interface NavLabels { + userGuide: string + openApp: string +} + +const userGuideSidebar = (prefix: string, l: SidebarLabels): DefaultTheme.SidebarItem[] => [ { - text: 'Getting Around', + text: l.gettingAround, items: [ - { text: 'Canvas Navigation', link: `${prefix}/user-guide/canvas-navigation` }, - { text: 'Selection & Manipulation', link: `${prefix}/user-guide/selection-and-manipulation` }, + { text: l.canvasNav, link: `${prefix}/user-guide/canvas-navigation` }, + { text: l.selection, link: `${prefix}/user-guide/selection-and-manipulation` }, ], }, { - text: 'Creating Content', + text: l.creatingContent, items: [ - { text: 'Drawing Shapes', link: `${prefix}/user-guide/drawing-shapes` }, - { text: 'Text Editing', link: `${prefix}/user-guide/text-editing` }, - { text: 'Pen Tool', link: `${prefix}/user-guide/pen-tool` }, + { text: l.shapes, link: `${prefix}/user-guide/drawing-shapes` }, + { text: l.text, link: `${prefix}/user-guide/text-editing` }, + { text: l.pen, link: `${prefix}/user-guide/pen-tool` }, ], }, { - text: 'Organizing & Managing', + text: l.organizing, items: [ - { text: 'Layers & Pages', link: `${prefix}/user-guide/layers-and-pages` }, - { text: 'Context Menu', link: `${prefix}/user-guide/context-menu` }, - { text: 'Exporting', link: `${prefix}/user-guide/exporting` }, + { text: l.layers, link: `${prefix}/user-guide/layers-and-pages` }, + { text: l.contextMenu, link: `${prefix}/user-guide/context-menu` }, + { text: l.exporting, link: `${prefix}/user-guide/exporting` }, ], }, { - text: 'Advanced Features', + text: l.advanced, items: [ - { text: 'Auto Layout', link: `${prefix}/user-guide/auto-layout` }, - { text: 'Components', link: `${prefix}/user-guide/components` }, - { text: 'Variables', link: `${prefix}/user-guide/variables` }, + { text: l.autoLayout, link: `${prefix}/user-guide/auto-layout` }, + { text: l.components, link: `${prefix}/user-guide/components` }, + { text: l.variables, link: `${prefix}/user-guide/variables` }, ], }, ] -const guideSidebar = (prefix = '') => [ +const guideSidebar = (prefix: string, l: SidebarLabels): DefaultTheme.SidebarItem[] => [ { - text: 'Guide', + text: l.guide, items: [ - { text: 'Getting Started', link: `${prefix}/guide/getting-started` }, - { text: 'Features', link: `${prefix}/guide/features` }, - { text: 'Architecture', link: `${prefix}/guide/architecture` }, - { text: 'Tech Stack', link: `${prefix}/guide/tech-stack` }, - { text: 'Comparison', link: `${prefix}/guide/comparison` }, - { text: 'Figma Feature Matrix', link: `${prefix}/guide/figma-comparison` }, + { text: l.gettingStarted, link: `${prefix}/guide/getting-started` }, + { text: l.features, link: `${prefix}/guide/features` }, + { text: l.architecture, link: `${prefix}/guide/architecture` }, + { text: l.techStack, link: `${prefix}/guide/tech-stack` }, + { text: l.comparison, link: `${prefix}/guide/comparison` }, + { text: l.figmaMatrix, link: `${prefix}/guide/figma-comparison` }, ], }, ] -const localeSidebar = (lang: string, labels: { gettingAround: string; creatingContent: string; organizing: string; advanced: string; canvasNav: string; selection: string; shapes: string; text: string; pen: string; layers: string; contextMenu: string; exporting: string; autoLayout: string; components: string; variables: string; guide: string; gettingStarted: string; features: string; architecture: string; techStack: string; comparison: string; figmaMatrix: string }) => ({ - [`/${lang}/user-guide/`]: [ - { text: labels.gettingAround, items: [ - { text: labels.canvasNav, link: `/${lang}/user-guide/canvas-navigation` }, - { text: labels.selection, link: `/${lang}/user-guide/selection-and-manipulation` }, - ]}, - { text: labels.creatingContent, items: [ - { text: labels.shapes, link: `/${lang}/user-guide/drawing-shapes` }, - { text: labels.text, link: `/${lang}/user-guide/text-editing` }, - { text: labels.pen, link: `/${lang}/user-guide/pen-tool` }, - ]}, - { text: labels.organizing, items: [ - { text: labels.layers, link: `/${lang}/user-guide/layers-and-pages` }, - { text: labels.contextMenu, link: `/${lang}/user-guide/context-menu` }, - { text: labels.exporting, link: `/${lang}/user-guide/exporting` }, - ]}, - { text: labels.advanced, items: [ - { text: labels.autoLayout, link: `/${lang}/user-guide/auto-layout` }, - { text: labels.components, link: `/${lang}/user-guide/components` }, - { text: labels.variables, link: `/${lang}/user-guide/variables` }, - ]}, - ], - [`/${lang}/`]: [ - { text: labels.guide, items: [ - { text: labels.gettingStarted, link: `/${lang}/guide/getting-started` }, - { text: labels.features, link: `/${lang}/guide/features` }, - { text: labels.architecture, link: `/${lang}/guide/architecture` }, - { text: labels.techStack, link: `/${lang}/guide/tech-stack` }, - { text: labels.comparison, link: `/${lang}/guide/comparison` }, - { text: labels.figmaMatrix, link: `/${lang}/guide/figma-comparison` }, - ]}, +const localeThemeConfig = ( + prefix: string, + nav: NavLabels, + sidebar: SidebarLabels, +): DefaultTheme.Config => ({ + nav: [ + { text: nav.userGuide, link: `${prefix}/user-guide/` }, + { text: nav.openApp, link: 'https://app.openpencil.dev' }, ], + sidebar: { + [`${prefix}/user-guide/`]: userGuideSidebar(prefix, sidebar), + [`${prefix}/`]: guideSidebar(prefix, sidebar), + }, }) +const EN: SidebarLabels = { gettingAround: 'Getting Around', creatingContent: 'Creating Content', organizing: 'Organizing & Managing', advanced: 'Advanced Features', canvasNav: 'Canvas Navigation', selection: 'Selection & Manipulation', shapes: 'Drawing Shapes', text: 'Text Editing', pen: 'Pen Tool', layers: 'Layers & Pages', contextMenu: 'Context Menu', exporting: 'Exporting', autoLayout: 'Auto Layout', components: 'Components', variables: 'Variables', guide: 'Guide', gettingStarted: 'Getting Started', features: 'Features', architecture: 'Architecture', techStack: 'Tech Stack', comparison: 'Comparison', figmaMatrix: 'Figma Feature Matrix' } + +const DE: SidebarLabels = { gettingAround: 'Erste Schritte', creatingContent: 'Inhalte erstellen', organizing: 'Organisieren', advanced: 'Erweitert', canvasNav: 'Canvas-Navigation', selection: 'Auswahl & Bearbeitung', shapes: 'Formen zeichnen', text: 'Textbearbeitung', pen: 'Stiftwerkzeug', layers: 'Ebenen & Seiten', contextMenu: 'Kontextmenü', exporting: 'Exportieren', autoLayout: 'Auto-Layout', components: 'Komponenten', variables: 'Variablen', guide: 'Anleitung', gettingStarted: 'Erste Schritte', features: 'Funktionen', architecture: 'Architektur', techStack: 'Tech-Stack', comparison: 'Vergleich', figmaMatrix: 'Figma-Funktionsmatrix' } + +const IT: SidebarLabels = { gettingAround: 'Orientamento', creatingContent: 'Creazione contenuti', organizing: 'Organizzazione', advanced: 'Avanzate', canvasNav: 'Navigazione canvas', selection: 'Selezione e manipolazione', shapes: 'Disegno forme', text: 'Modifica testo', pen: 'Strumento penna', layers: 'Livelli e pagine', contextMenu: 'Menu contestuale', exporting: 'Esportazione', autoLayout: 'Auto-layout', components: 'Componenti', variables: 'Variabili', guide: 'Guida', gettingStarted: 'Per iniziare', features: 'Funzionalità', architecture: 'Architettura', techStack: 'Stack tecnologico', comparison: 'Confronto', figmaMatrix: 'Matrice funzionalità Figma' } + +const FR: SidebarLabels = { gettingAround: 'Prise en main', creatingContent: 'Création de contenu', organizing: 'Organisation', advanced: 'Avancé', canvasNav: 'Navigation sur le canevas', selection: 'Sélection et manipulation', shapes: 'Dessiner des formes', text: 'Édition de texte', pen: 'Outil plume', layers: 'Calques et pages', contextMenu: 'Menu contextuel', exporting: 'Exportation', autoLayout: 'Mise en page auto', components: 'Composants', variables: 'Variables', guide: 'Guide', gettingStarted: 'Premiers pas', features: 'Fonctionnalités', architecture: 'Architecture', techStack: 'Stack technique', comparison: 'Comparaison', figmaMatrix: 'Matrice des fonctionnalités Figma' } + +const ES: SidebarLabels = { gettingAround: 'Orientación', creatingContent: 'Crear contenido', organizing: 'Organizar', advanced: 'Avanzado', canvasNav: 'Navegación del lienzo', selection: 'Selección y manipulación', shapes: 'Dibujar formas', text: 'Edición de texto', pen: 'Herramienta pluma', layers: 'Capas y páginas', contextMenu: 'Menú contextual', exporting: 'Exportar', autoLayout: 'Auto-layout', components: 'Componentes', variables: 'Variables', guide: 'Guía', gettingStarted: 'Primeros pasos', features: 'Características', architecture: 'Arquitectura', techStack: 'Stack tecnológico', comparison: 'Comparación', figmaMatrix: 'Matriz de funcionalidades Figma' } + +const PL: SidebarLabels = { gettingAround: 'Nawigacja', creatingContent: 'Tworzenie treści', organizing: 'Organizacja', advanced: 'Zaawansowane', canvasNav: 'Nawigacja po płótnie', selection: 'Zaznaczanie i edycja', shapes: 'Rysowanie kształtów', text: 'Edycja tekstu', pen: 'Narzędzie pióro', layers: 'Warstwy i strony', contextMenu: 'Menu kontekstowe', exporting: 'Eksportowanie', autoLayout: 'Auto-layout', components: 'Komponenty', variables: 'Zmienne', guide: 'Przewodnik', gettingStarted: 'Rozpoczęcie pracy', features: 'Funkcje', architecture: 'Architektura', techStack: 'Stack technologiczny', comparison: 'Porównanie', figmaMatrix: 'Matryca funkcji Figma' } + export default defineConfig({ title: 'OpenPencil', description: 'Open-source, AI-native design editor. Figma alternative built from scratch with full .fig file compatibility.', @@ -97,12 +120,40 @@ export default defineConfig({ ], locales: { - root: { label: 'English', lang: 'en' }, - de: { label: 'Deutsch', lang: 'de' }, - it: { label: 'Italiano', lang: 'it' }, - fr: { label: 'Français', lang: 'fr' }, - es: { label: 'Español', lang: 'es' }, - pl: { label: 'Polski', lang: 'pl' }, + root: { + label: 'English', + lang: 'en', + }, + de: { + label: 'Deutsch', + lang: 'de', + description: 'Open-Source, KI-nativer Design-Editor. Figma-Alternative.', + themeConfig: localeThemeConfig('/de', { userGuide: 'Benutzerhandbuch', openApp: 'App öffnen' }, DE), + }, + it: { + label: 'Italiano', + lang: 'it', + description: 'Editor di design open-source, IA-nativo. Alternativa a Figma.', + themeConfig: localeThemeConfig('/it', { userGuide: 'Guida utente', openApp: 'Apri app' }, IT), + }, + fr: { + label: 'Français', + lang: 'fr', + description: 'Éditeur de design open-source, IA-natif. Alternative à Figma.', + themeConfig: localeThemeConfig('/fr', { userGuide: 'Guide utilisateur', openApp: 'Ouvrir l\'app' }, FR), + }, + es: { + label: 'Español', + lang: 'es', + description: 'Editor de diseño open-source, IA-nativo. Alternativa a Figma.', + themeConfig: localeThemeConfig('/es', { userGuide: 'Guía del usuario', openApp: 'Abrir app' }, ES), + }, + pl: { + label: 'Polski', + lang: 'pl', + description: 'Open-source\'owy edytor graficzny z natywnym AI. Alternatywa dla Figmy.', + themeConfig: localeThemeConfig('/pl', { userGuide: 'Podręcznik', openApp: 'Otwórz app' }, PL), + }, }, themeConfig: { @@ -116,7 +167,7 @@ export default defineConfig({ ], sidebar: { - '/user-guide/': userGuideSidebar(), + '/user-guide/': userGuideSidebar('', EN), '/reference/': [ { text: 'Reference', @@ -131,7 +182,7 @@ export default defineConfig({ }, ], '/': [ - ...guideSidebar(), + ...guideSidebar('', EN), { text: 'Development', items: [ @@ -142,11 +193,6 @@ export default defineConfig({ ], }, ], - ...localeSidebar('de', { gettingAround: 'Erste Schritte', creatingContent: 'Inhalte erstellen', organizing: 'Organisieren', advanced: 'Erweitert', canvasNav: 'Canvas-Navigation', selection: 'Auswahl & Bearbeitung', shapes: 'Formen zeichnen', text: 'Textbearbeitung', pen: 'Stiftwerkzeug', layers: 'Ebenen & Seiten', contextMenu: 'Kontextmenü', exporting: 'Exportieren', autoLayout: 'Auto-Layout', components: 'Komponenten', variables: 'Variablen', guide: 'Anleitung', gettingStarted: 'Erste Schritte', features: 'Funktionen', architecture: 'Architektur', techStack: 'Tech-Stack', comparison: 'Vergleich', figmaMatrix: 'Figma-Funktionsmatrix' }), - ...localeSidebar('it', { gettingAround: 'Orientamento', creatingContent: 'Creazione contenuti', organizing: 'Organizzazione', advanced: 'Avanzate', canvasNav: 'Navigazione canvas', selection: 'Selezione e manipolazione', shapes: 'Disegno forme', text: 'Modifica testo', pen: 'Strumento penna', layers: 'Livelli e pagine', contextMenu: 'Menu contestuale', exporting: 'Esportazione', autoLayout: 'Auto-layout', components: 'Componenti', variables: 'Variabili', guide: 'Guida', gettingStarted: 'Per iniziare', features: 'Funzionalità', architecture: 'Architettura', techStack: 'Stack tecnologico', comparison: 'Confronto', figmaMatrix: 'Matrice funzionalità Figma' }), - ...localeSidebar('fr', { gettingAround: 'Prise en main', creatingContent: 'Création de contenu', organizing: 'Organisation', advanced: 'Avancé', canvasNav: 'Navigation sur le canevas', selection: 'Sélection et manipulation', shapes: 'Dessiner des formes', text: 'Édition de texte', pen: 'Outil plume', layers: 'Calques et pages', contextMenu: 'Menu contextuel', exporting: 'Exportation', autoLayout: 'Mise en page auto', components: 'Composants', variables: 'Variables', guide: 'Guide', gettingStarted: 'Premiers pas', features: 'Fonctionnalités', architecture: 'Architecture', techStack: 'Stack technique', comparison: 'Comparaison', figmaMatrix: 'Matrice des fonctionnalités Figma' }), - ...localeSidebar('es', { gettingAround: 'Orientación', creatingContent: 'Crear contenido', organizing: 'Organizar', advanced: 'Avanzado', canvasNav: 'Navegación del lienzo', selection: 'Selección y manipulación', shapes: 'Dibujar formas', text: 'Edición de texto', pen: 'Herramienta pluma', layers: 'Capas y páginas', contextMenu: 'Menú contextual', exporting: 'Exportar', autoLayout: 'Auto-layout', components: 'Componentes', variables: 'Variables', guide: 'Guía', gettingStarted: 'Primeros pasos', features: 'Características', architecture: 'Arquitectura', techStack: 'Stack tecnológico', comparison: 'Comparación', figmaMatrix: 'Matriz de funcionalidades Figma' }), - ...localeSidebar('pl', { gettingAround: 'Nawigacja', creatingContent: 'Tworzenie treści', organizing: 'Organizacja', advanced: 'Zaawansowane', canvasNav: 'Nawigacja po płótnie', selection: 'Zaznaczanie i edycja', shapes: 'Rysowanie kształtów', text: 'Edycja tekstu', pen: 'Narzędzie pióro', layers: 'Warstwy i strony', contextMenu: 'Menu kontekstowe', exporting: 'Eksportowanie', autoLayout: 'Auto-layout', components: 'Komponenty', variables: 'Zmienne', guide: 'Przewodnik', gettingStarted: 'Rozpoczęcie pracy', features: 'Funkcje', architecture: 'Architektura', techStack: 'Stack technologiczny', comparison: 'Porównanie', figmaMatrix: 'Matryca funkcji Figma' }), }, socialLinks: [