feat(examples): translate ExamplesPage + ExamplesGallery to 9 locales
The /examples gallery is fully localised:
- Header (heading + subtitle).
- Search input placeholder + aria-label + the clear button.
- Match-count tag with i18next pluralisation (handles _one /
_other and Russian's _few / _many).
- Category and Difficulty filter labels + their button labels
(basics / sensors / displays / communication / games / robotics
/ circuits; beginner / intermediate / advanced).
- Per-card "Copy shareable link" tooltip.
- Empty-state copy with two variants (with-search / without-
search) interpolating the search query.
- Reset-filters button.
- The library-install progress overlay copy from
ExamplesPage.tsx ("Installing libraries (N/M)") with done/total
interpolation.
Internal /editor link uses localize() so a Spanish reader who
clicks an example lands on /es/editor.
Hand-translated for all 8 non-English locales. Per-example titles
+ descriptions are NOT i18n yet — they live in the
src/data/examples* tables and would need a separate pipeline.
DocsPage (2715 lines of prose) deferred too — best handled by
running scripts/translate-i18n.mjs once the keys are extracted.
This commit is contained in:
parent
b086be73fe
commit
4df81a3eda
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { exampleProjects, type ExampleProject } from '../../data/examples';
|
||||
import { ExampleThumbnail } from './ExampleThumbnail';
|
||||
import './ExamplesGallery.css';
|
||||
|
|
@ -44,6 +45,7 @@ function getBoardFilter(example: ExampleProject): string {
|
|||
}
|
||||
|
||||
export const ExamplesGallery: React.FC<ExamplesGalleryProps> = ({ onLoadExample }) => {
|
||||
const { t } = useTranslation();
|
||||
const [selectedBoard, setSelectedBoard] = useState<string>('all');
|
||||
const [selectedCategory, setSelectedCategory] = useState<ExampleProject['category'] | 'all'>(
|
||||
'all',
|
||||
|
|
@ -193,8 +195,8 @@ export const ExamplesGallery: React.FC<ExamplesGalleryProps> = ({ onLoadExample
|
|||
return (
|
||||
<div className="examples-gallery">
|
||||
<div className="examples-header">
|
||||
<h1>Featured Projects</h1>
|
||||
<p>Explore and run example projects — organized by board</p>
|
||||
<h1>{t('examples.heading')}</h1>
|
||||
<p>{t('examples.subtitle')}</p>
|
||||
</div>
|
||||
|
||||
{/* Search */}
|
||||
|
|
@ -218,18 +220,18 @@ export const ExamplesGallery: React.FC<ExamplesGalleryProps> = ({ onLoadExample
|
|||
<input
|
||||
type="search"
|
||||
className="examples-search-input"
|
||||
placeholder="Search examples — try 'esp32 oled', 'blink', 'dht'…"
|
||||
placeholder={t('examples.searchPlaceholder')}
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
aria-label="Search examples"
|
||||
aria-label={t('examples.searchLabel')}
|
||||
/>
|
||||
{search && (
|
||||
<button
|
||||
type="button"
|
||||
className="examples-search-clear"
|
||||
onClick={() => setSearch('')}
|
||||
aria-label="Clear search"
|
||||
title="Clear"
|
||||
aria-label={t('examples.clearSearch')}
|
||||
title={t('examples.clear')}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
|
|
@ -237,8 +239,7 @@ export const ExamplesGallery: React.FC<ExamplesGalleryProps> = ({ onLoadExample
|
|||
</div>
|
||||
{searchTokens.length > 0 && (
|
||||
<span className="examples-search-count">
|
||||
{filteredExamples.length} match
|
||||
{filteredExamples.length === 1 ? '' : 'es'}
|
||||
{t('examples.matchCount', { count: filteredExamples.length })}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -267,7 +268,7 @@ export const ExamplesGallery: React.FC<ExamplesGalleryProps> = ({ onLoadExample
|
|||
{/* Category + Difficulty filters */}
|
||||
<div className="examples-filters">
|
||||
<div className="filter-group">
|
||||
<label>Category:</label>
|
||||
<label>{t('examples.filters.categoryLabel')}</label>
|
||||
<div className="filter-buttons">
|
||||
{(
|
||||
[
|
||||
|
|
@ -287,14 +288,14 @@ export const ExamplesGallery: React.FC<ExamplesGalleryProps> = ({ onLoadExample
|
|||
onClick={() => setSelectedCategory(cat)}
|
||||
>
|
||||
{cat !== 'all' && getCategoryIcon(cat as ExampleProject['category'])}{' '}
|
||||
{cat === 'all' ? 'All' : cat.charAt(0).toUpperCase() + cat.slice(1)}
|
||||
{t(`examples.filters.category.${cat}`)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="filter-group">
|
||||
<label>Difficulty:</label>
|
||||
<label>{t('examples.filters.difficultyLabel')}</label>
|
||||
<div className="filter-buttons">
|
||||
{(['all', 'beginner', 'intermediate', 'advanced'] as const).map((diff) => (
|
||||
<button
|
||||
|
|
@ -302,7 +303,7 @@ export const ExamplesGallery: React.FC<ExamplesGalleryProps> = ({ onLoadExample
|
|||
className={`filter-button ${selectedDifficulty === diff ? 'active' : ''}`}
|
||||
onClick={() => setSelectedDifficulty(diff)}
|
||||
>
|
||||
{diff === 'all' ? 'All' : diff.charAt(0).toUpperCase() + diff.slice(1)}
|
||||
{t(`examples.filters.difficulty.${diff}`)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
|
@ -356,7 +357,7 @@ export const ExamplesGallery: React.FC<ExamplesGalleryProps> = ({ onLoadExample
|
|||
<button
|
||||
className="example-copy-link"
|
||||
onClick={(e) => handleCopyLink(e, example.id)}
|
||||
title="Copy shareable link"
|
||||
title={t('examples.copyLink')}
|
||||
>
|
||||
{copiedId === example.id ? (
|
||||
<svg
|
||||
|
|
@ -397,9 +398,9 @@ export const ExamplesGallery: React.FC<ExamplesGalleryProps> = ({ onLoadExample
|
|||
{filteredExamples.length === 0 && (
|
||||
<div className="examples-empty">
|
||||
<p>
|
||||
No examples found
|
||||
{searchTokens.length > 0 ? ` for "${search.trim()}"` : ''} with the
|
||||
selected filters
|
||||
{searchTokens.length > 0
|
||||
? t('examples.emptyForQuery', { query: search.trim() })
|
||||
: t('examples.empty')}
|
||||
</p>
|
||||
{(searchTokens.length > 0 ||
|
||||
selectedBoard !== 'all' ||
|
||||
|
|
@ -414,7 +415,7 @@ export const ExamplesGallery: React.FC<ExamplesGalleryProps> = ({ onLoadExample
|
|||
setSelectedDifficulty('all');
|
||||
}}
|
||||
>
|
||||
Reset filters
|
||||
{t('examples.resetFilters')}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -77,6 +77,41 @@
|
|||
"ctaPaypal": "Über PayPal spenden"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"heading": "Empfohlene Projekte",
|
||||
"subtitle": "Beispielprojekte erkunden und ausführen — nach Board sortiert",
|
||||
"searchPlaceholder": "Beispiele suchen — z. B. 'esp32 oled', 'blink', 'dht'…",
|
||||
"searchLabel": "Beispiele suchen",
|
||||
"clearSearch": "Suche zurücksetzen",
|
||||
"clear": "Löschen",
|
||||
"matchCount_one": "{{count}} Treffer",
|
||||
"matchCount_other": "{{count}} Treffer",
|
||||
"filters": {
|
||||
"categoryLabel": "Kategorie:",
|
||||
"difficultyLabel": "Schwierigkeit:",
|
||||
"category": {
|
||||
"all": "Alle",
|
||||
"basics": "Grundlagen",
|
||||
"sensors": "Sensoren",
|
||||
"displays": "Displays",
|
||||
"communication": "Kommunikation",
|
||||
"games": "Spiele",
|
||||
"robotics": "Robotik",
|
||||
"circuits": "Schaltungen"
|
||||
},
|
||||
"difficulty": {
|
||||
"all": "Alle",
|
||||
"beginner": "Anfänger",
|
||||
"intermediate": "Fortgeschritten",
|
||||
"advanced": "Profi"
|
||||
}
|
||||
},
|
||||
"copyLink": "Teilbaren Link kopieren",
|
||||
"empty": "Keine Beispiele mit den gewählten Filtern gefunden",
|
||||
"emptyForQuery": "Keine Beispiele für „{{query}}\" mit den gewählten Filtern gefunden",
|
||||
"resetFilters": "Filter zurücksetzen",
|
||||
"installing": "Bibliotheken werden installiert ({{done}}/{{total}})"
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
"title": "Über Velxio",
|
||||
|
|
|
|||
|
|
@ -77,6 +77,41 @@
|
|||
"ctaPaypal": "Donate via PayPal"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"heading": "Featured Projects",
|
||||
"subtitle": "Explore and run example projects — organized by board",
|
||||
"searchPlaceholder": "Search examples — try 'esp32 oled', 'blink', 'dht'…",
|
||||
"searchLabel": "Search examples",
|
||||
"clearSearch": "Clear search",
|
||||
"clear": "Clear",
|
||||
"matchCount_one": "{{count}} match",
|
||||
"matchCount_other": "{{count}} matches",
|
||||
"filters": {
|
||||
"categoryLabel": "Category:",
|
||||
"difficultyLabel": "Difficulty:",
|
||||
"category": {
|
||||
"all": "All",
|
||||
"basics": "Basics",
|
||||
"sensors": "Sensors",
|
||||
"displays": "Displays",
|
||||
"communication": "Communication",
|
||||
"games": "Games",
|
||||
"robotics": "Robotics",
|
||||
"circuits": "Circuits"
|
||||
},
|
||||
"difficulty": {
|
||||
"all": "All",
|
||||
"beginner": "Beginner",
|
||||
"intermediate": "Intermediate",
|
||||
"advanced": "Advanced"
|
||||
}
|
||||
},
|
||||
"copyLink": "Copy shareable link",
|
||||
"empty": "No examples found with the selected filters",
|
||||
"emptyForQuery": "No examples found for \"{{query}}\" with the selected filters",
|
||||
"resetFilters": "Reset filters",
|
||||
"installing": "Installing libraries ({{done}}/{{total}})"
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
"title": "About Velxio",
|
||||
|
|
|
|||
|
|
@ -77,6 +77,41 @@
|
|||
"ctaPaypal": "Donar con PayPal"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"heading": "Proyectos destacados",
|
||||
"subtitle": "Explora y ejecuta proyectos de ejemplo — organizados por placa",
|
||||
"searchPlaceholder": "Buscar ejemplos — prueba 'esp32 oled', 'blink', 'dht'…",
|
||||
"searchLabel": "Buscar ejemplos",
|
||||
"clearSearch": "Limpiar búsqueda",
|
||||
"clear": "Limpiar",
|
||||
"matchCount_one": "{{count}} coincidencia",
|
||||
"matchCount_other": "{{count}} coincidencias",
|
||||
"filters": {
|
||||
"categoryLabel": "Categoría:",
|
||||
"difficultyLabel": "Dificultad:",
|
||||
"category": {
|
||||
"all": "Todas",
|
||||
"basics": "Básicos",
|
||||
"sensors": "Sensores",
|
||||
"displays": "Pantallas",
|
||||
"communication": "Comunicación",
|
||||
"games": "Juegos",
|
||||
"robotics": "Robótica",
|
||||
"circuits": "Circuitos"
|
||||
},
|
||||
"difficulty": {
|
||||
"all": "Todas",
|
||||
"beginner": "Principiante",
|
||||
"intermediate": "Intermedio",
|
||||
"advanced": "Avanzado"
|
||||
}
|
||||
},
|
||||
"copyLink": "Copiar enlace para compartir",
|
||||
"empty": "No se encontraron ejemplos con los filtros seleccionados",
|
||||
"emptyForQuery": "No se encontraron ejemplos para \"{{query}}\" con los filtros seleccionados",
|
||||
"resetFilters": "Restablecer filtros",
|
||||
"installing": "Instalando librerías ({{done}}/{{total}})"
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
"title": "Acerca de Velxio",
|
||||
|
|
|
|||
|
|
@ -77,6 +77,41 @@
|
|||
"ctaPaypal": "Faire un don via PayPal"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"heading": "Projets en vedette",
|
||||
"subtitle": "Explorez et exécutez des projets d'exemple — organisés par carte",
|
||||
"searchPlaceholder": "Rechercher des exemples — essayez 'esp32 oled', 'blink', 'dht'…",
|
||||
"searchLabel": "Rechercher des exemples",
|
||||
"clearSearch": "Effacer la recherche",
|
||||
"clear": "Effacer",
|
||||
"matchCount_one": "{{count}} résultat",
|
||||
"matchCount_other": "{{count}} résultats",
|
||||
"filters": {
|
||||
"categoryLabel": "Catégorie :",
|
||||
"difficultyLabel": "Difficulté :",
|
||||
"category": {
|
||||
"all": "Toutes",
|
||||
"basics": "Bases",
|
||||
"sensors": "Capteurs",
|
||||
"displays": "Écrans",
|
||||
"communication": "Communication",
|
||||
"games": "Jeux",
|
||||
"robotics": "Robotique",
|
||||
"circuits": "Circuits"
|
||||
},
|
||||
"difficulty": {
|
||||
"all": "Toutes",
|
||||
"beginner": "Débutant",
|
||||
"intermediate": "Intermédiaire",
|
||||
"advanced": "Avancé"
|
||||
}
|
||||
},
|
||||
"copyLink": "Copier le lien partageable",
|
||||
"empty": "Aucun exemple trouvé avec les filtres sélectionnés",
|
||||
"emptyForQuery": "Aucun exemple trouvé pour « {{query}} » avec les filtres sélectionnés",
|
||||
"resetFilters": "Réinitialiser les filtres",
|
||||
"installing": "Installation des bibliothèques ({{done}}/{{total}})"
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
"title": "À propos de Velxio",
|
||||
|
|
|
|||
|
|
@ -77,6 +77,41 @@
|
|||
"ctaPaypal": "Dona con PayPal"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"heading": "Progetti in evidenza",
|
||||
"subtitle": "Esplora ed esegui progetti di esempio — organizzati per scheda",
|
||||
"searchPlaceholder": "Cerca esempi — prova 'esp32 oled', 'blink', 'dht'…",
|
||||
"searchLabel": "Cerca esempi",
|
||||
"clearSearch": "Cancella ricerca",
|
||||
"clear": "Cancella",
|
||||
"matchCount_one": "{{count}} risultato",
|
||||
"matchCount_other": "{{count}} risultati",
|
||||
"filters": {
|
||||
"categoryLabel": "Categoria:",
|
||||
"difficultyLabel": "Difficoltà:",
|
||||
"category": {
|
||||
"all": "Tutte",
|
||||
"basics": "Basi",
|
||||
"sensors": "Sensori",
|
||||
"displays": "Display",
|
||||
"communication": "Comunicazione",
|
||||
"games": "Giochi",
|
||||
"robotics": "Robotica",
|
||||
"circuits": "Circuiti"
|
||||
},
|
||||
"difficulty": {
|
||||
"all": "Tutte",
|
||||
"beginner": "Principiante",
|
||||
"intermediate": "Intermedio",
|
||||
"advanced": "Avanzato"
|
||||
}
|
||||
},
|
||||
"copyLink": "Copia link condivisibile",
|
||||
"empty": "Nessun esempio trovato con i filtri selezionati",
|
||||
"emptyForQuery": "Nessun esempio trovato per \"{{query}}\" con i filtri selezionati",
|
||||
"resetFilters": "Reimposta filtri",
|
||||
"installing": "Installazione librerie ({{done}}/{{total}})"
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
"title": "Informazioni su Velxio",
|
||||
|
|
|
|||
|
|
@ -77,6 +77,40 @@
|
|||
"ctaPaypal": "PayPal で寄付する"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"heading": "おすすめプロジェクト",
|
||||
"subtitle": "サンプルプロジェクトを探して実行 — ボード別に整理",
|
||||
"searchPlaceholder": "サンプルを検索 — 例:「esp32 oled」「blink」「dht」…",
|
||||
"searchLabel": "サンプルを検索",
|
||||
"clearSearch": "検索をクリア",
|
||||
"clear": "クリア",
|
||||
"matchCount_other": "{{count}} 件",
|
||||
"filters": {
|
||||
"categoryLabel": "カテゴリ:",
|
||||
"difficultyLabel": "難易度:",
|
||||
"category": {
|
||||
"all": "すべて",
|
||||
"basics": "基礎",
|
||||
"sensors": "センサー",
|
||||
"displays": "ディスプレイ",
|
||||
"communication": "通信",
|
||||
"games": "ゲーム",
|
||||
"robotics": "ロボティクス",
|
||||
"circuits": "回路"
|
||||
},
|
||||
"difficulty": {
|
||||
"all": "すべて",
|
||||
"beginner": "初級",
|
||||
"intermediate": "中級",
|
||||
"advanced": "上級"
|
||||
}
|
||||
},
|
||||
"copyLink": "共有リンクをコピー",
|
||||
"empty": "選択したフィルタに一致するサンプルが見つかりません",
|
||||
"emptyForQuery": "「{{query}}」に一致するサンプルが見つかりません(選択したフィルタ条件で)",
|
||||
"resetFilters": "フィルタをリセット",
|
||||
"installing": "ライブラリをインストール中({{done}}/{{total}})"
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
"title": "Velxio について",
|
||||
|
|
|
|||
|
|
@ -77,6 +77,41 @@
|
|||
"ctaPaypal": "Doar via PayPal"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"heading": "Projetos em destaque",
|
||||
"subtitle": "Explore e execute projetos de exemplo — organizados por placa",
|
||||
"searchPlaceholder": "Buscar exemplos — tente 'esp32 oled', 'blink', 'dht'…",
|
||||
"searchLabel": "Buscar exemplos",
|
||||
"clearSearch": "Limpar busca",
|
||||
"clear": "Limpar",
|
||||
"matchCount_one": "{{count}} resultado",
|
||||
"matchCount_other": "{{count}} resultados",
|
||||
"filters": {
|
||||
"categoryLabel": "Categoria:",
|
||||
"difficultyLabel": "Dificuldade:",
|
||||
"category": {
|
||||
"all": "Todas",
|
||||
"basics": "Básicos",
|
||||
"sensors": "Sensores",
|
||||
"displays": "Displays",
|
||||
"communication": "Comunicação",
|
||||
"games": "Jogos",
|
||||
"robotics": "Robótica",
|
||||
"circuits": "Circuitos"
|
||||
},
|
||||
"difficulty": {
|
||||
"all": "Todas",
|
||||
"beginner": "Iniciante",
|
||||
"intermediate": "Intermediário",
|
||||
"advanced": "Avançado"
|
||||
}
|
||||
},
|
||||
"copyLink": "Copiar link compartilhável",
|
||||
"empty": "Nenhum exemplo encontrado com os filtros selecionados",
|
||||
"emptyForQuery": "Nenhum exemplo encontrado para \"{{query}}\" com os filtros selecionados",
|
||||
"resetFilters": "Limpar filtros",
|
||||
"installing": "Instalando bibliotecas ({{done}}/{{total}})"
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
"title": "Sobre o Velxio",
|
||||
|
|
|
|||
|
|
@ -77,6 +77,43 @@
|
|||
"ctaPaypal": "Пожертвовать через PayPal"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"heading": "Избранные проекты",
|
||||
"subtitle": "Изучайте и запускайте примеры — сгруппированные по плате",
|
||||
"searchPlaceholder": "Поиск примеров — попробуйте 'esp32 oled', 'blink', 'dht'…",
|
||||
"searchLabel": "Поиск примеров",
|
||||
"clearSearch": "Очистить поиск",
|
||||
"clear": "Очистить",
|
||||
"matchCount_one": "{{count}} совпадение",
|
||||
"matchCount_few": "{{count}} совпадения",
|
||||
"matchCount_many": "{{count}} совпадений",
|
||||
"matchCount_other": "{{count}} совпадений",
|
||||
"filters": {
|
||||
"categoryLabel": "Категория:",
|
||||
"difficultyLabel": "Сложность:",
|
||||
"category": {
|
||||
"all": "Все",
|
||||
"basics": "Основы",
|
||||
"sensors": "Датчики",
|
||||
"displays": "Дисплеи",
|
||||
"communication": "Связь",
|
||||
"games": "Игры",
|
||||
"robotics": "Робототехника",
|
||||
"circuits": "Схемы"
|
||||
},
|
||||
"difficulty": {
|
||||
"all": "Все",
|
||||
"beginner": "Новичок",
|
||||
"intermediate": "Средний",
|
||||
"advanced": "Продвинутый"
|
||||
}
|
||||
},
|
||||
"copyLink": "Скопировать ссылку для шаринга",
|
||||
"empty": "Не найдено примеров с выбранными фильтрами",
|
||||
"emptyForQuery": "Не найдено примеров по запросу «{{query}}» с выбранными фильтрами",
|
||||
"resetFilters": "Сбросить фильтры",
|
||||
"installing": "Установка библиотек ({{done}}/{{total}})"
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
"title": "О Velxio",
|
||||
|
|
|
|||
|
|
@ -77,6 +77,40 @@
|
|||
"ctaPaypal": "通过 PayPal 捐赠"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"heading": "精选项目",
|
||||
"subtitle": "浏览并运行示例项目 —— 按开发板分类",
|
||||
"searchPlaceholder": "搜索示例 —— 试试 'esp32 oled'、'blink'、'dht'…",
|
||||
"searchLabel": "搜索示例",
|
||||
"clearSearch": "清除搜索",
|
||||
"clear": "清除",
|
||||
"matchCount_other": "{{count}} 个结果",
|
||||
"filters": {
|
||||
"categoryLabel": "分类:",
|
||||
"difficultyLabel": "难度:",
|
||||
"category": {
|
||||
"all": "全部",
|
||||
"basics": "基础",
|
||||
"sensors": "传感器",
|
||||
"displays": "显示器",
|
||||
"communication": "通信",
|
||||
"games": "游戏",
|
||||
"robotics": "机器人",
|
||||
"circuits": "电路"
|
||||
},
|
||||
"difficulty": {
|
||||
"all": "全部",
|
||||
"beginner": "入门",
|
||||
"intermediate": "中级",
|
||||
"advanced": "高级"
|
||||
}
|
||||
},
|
||||
"copyLink": "复制可分享链接",
|
||||
"empty": "在所选筛选条件下未找到示例",
|
||||
"emptyForQuery": "在所选筛选条件下未找到与「{{query}}」匹配的示例",
|
||||
"resetFilters": "重置筛选",
|
||||
"installing": "正在安装库({{done}}/{{total}})"
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
"title": "关于 Velxio",
|
||||
|
|
|
|||
|
|
@ -6,14 +6,18 @@
|
|||
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ExamplesGallery } from '../components/examples/ExamplesGallery';
|
||||
import { AppHeader } from '../components/layout/AppHeader';
|
||||
import { useLocalizedHref } from '../i18n/useLocalizedNavigate';
|
||||
import { useSEO } from '../utils/useSEO';
|
||||
import { getSeoMeta } from '../seoRoutes';
|
||||
import { loadExample, type LibraryInstallProgress } from '../utils/loadExample';
|
||||
import type { ExampleProject } from '../data/examples';
|
||||
|
||||
export const ExamplesPage: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
const localize = useLocalizedHref();
|
||||
useSEO(getSeoMeta('/examples')!);
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
|
@ -21,7 +25,7 @@ export const ExamplesPage: React.FC = () => {
|
|||
|
||||
const handleLoadExample = async (example: ExampleProject) => {
|
||||
await loadExample(example, setInstalling);
|
||||
navigate('/editor');
|
||||
navigate(localize('/editor'));
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -61,7 +65,10 @@ export const ExamplesPage: React.FC = () => {
|
|||
}}
|
||||
>
|
||||
<div style={{ fontSize: 14, color: '#ccc', marginBottom: 12 }}>
|
||||
Installing libraries ({installing.done + 1}/{installing.total})
|
||||
{t('examples.installing', {
|
||||
done: installing.done + 1,
|
||||
total: installing.total,
|
||||
})}
|
||||
</div>
|
||||
<div style={{ fontSize: 16, color: '#00e5ff', fontWeight: 600, marginBottom: 16 }}>
|
||||
{installing.current}
|
||||
|
|
|
|||
Loading…
Reference in New Issue