feat(editor): translate EditorToolbar to 9 locales (Editor block 1)

The top toolbar of the editor is now fully localised — compile / run /
stop / reset, the compile-all / run-all variants when multiple boards
are open, the language-mode select, libraries / import / export /
upload-firmware actions, and the missing-library hint banner.

Strings live under editor.toolbar.* in src/i18n/locales/<locale>/common.json.
Hand-translated for all 8 non-English locales. Brand and product
names (Arduino, MicroPython, Ctrl+B, .hex / .bin / .elf / .ihex,
GitHub Sponsors) preserved as-is.

Editor strings still pending: file explorer, file tabs, simulator
canvas, component picker, library manager modal, save / share /
project modals.
This commit is contained in:
David Montero Crespo 2026-05-09 03:05:51 -03:00
parent ca081f8e09
commit 11012ec0e1
10 changed files with 320 additions and 21 deletions

View File

@ -1,4 +1,5 @@
import { useState, useCallback, useRef, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { useEditorStore } from '../../store/useEditorStore';
import { useSimulatorStore } from '../../store/useSimulatorStore';
import type { BoardKind, LanguageMode } from '../../types/board';
@ -71,6 +72,7 @@ export const EditorToolbar = ({
centerSlot,
rightSlot,
}: EditorToolbarProps) => {
const { t } = useTranslation();
const { files, codeChangedSinceLastCompile, markCompiled } = useEditorStore();
const {
boards,
@ -629,7 +631,7 @@ export const EditorToolbar = ({
if (activeBoardId)
setBoardLanguageMode(activeBoardId, e.target.value as LanguageMode);
}}
title="Language mode"
title={t('editor.toolbar.languageMode')}
style={{
background: '#2d2d2d',
color: '#ccc',
@ -655,12 +657,12 @@ export const EditorToolbar = ({
className="tb-btn tb-btn-compile"
title={
!activeBoard
? 'Add a board to compile'
? t('editor.toolbar.compile.addBoard')
: compiling
? 'Loading…'
? t('editor.toolbar.compile.loading')
: activeBoard?.languageMode === 'micropython'
? 'Load MicroPython'
: 'Compile (Ctrl+B)'
? t('editor.toolbar.compile.loadMicropython')
: t('editor.toolbar.compile.compile')
}
>
{compiling ? (
@ -702,10 +704,10 @@ export const EditorToolbar = ({
className="tb-btn tb-btn-run"
title={
!activeBoard
? 'Add a board to run'
? t('editor.toolbar.run.addBoard')
: activeBoard?.languageMode === 'micropython'
? 'Run MicroPython'
: 'Run (auto-compiles if needed)'
? t('editor.toolbar.run.runMicropython')
: t('editor.toolbar.run.run')
}
>
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" stroke="none">
@ -718,7 +720,7 @@ export const EditorToolbar = ({
onClick={handleStop}
disabled={!running}
className="tb-btn tb-btn-stop"
title="Stop"
title={t('editor.toolbar.stop')}
>
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" stroke="none">
<rect x="3" y="3" width="18" height="18" rx="2" />
@ -730,7 +732,7 @@ export const EditorToolbar = ({
onClick={handleReset}
disabled={!compiledHex && !activeBoard?.compiledProgram}
className="tb-btn tb-btn-reset"
title="Reset"
title={t('editor.toolbar.reset')}
>
<svg
width="18"
@ -756,7 +758,7 @@ export const EditorToolbar = ({
onClick={handleCompileAll}
disabled={compileAllRunning}
className="tb-btn tb-btn-compile-all"
title="Compile all boards"
title={t('editor.toolbar.compileAll')}
>
<svg
width="18"
@ -778,7 +780,7 @@ export const EditorToolbar = ({
onClick={handleRunAll}
disabled={running}
className="tb-btn tb-btn-run-all"
title="Run all boards"
title={t('editor.toolbar.runAll')}
>
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" stroke="none">
<polygon points="3,3 11,12 3,21" />
@ -817,7 +819,7 @@ export const EditorToolbar = ({
setLibManagerOpen(true);
}}
className="tb-btn-libraries"
title="Search and install Arduino libraries"
title={t('editor.toolbar.libraries.title')}
>
<svg
width="16"
@ -833,7 +835,7 @@ export const EditorToolbar = ({
<path d="m3.3 7 8.7 5 8.7-5" />
<path d="M12 22V12" />
</svg>
<span className="tb-libraries-label">Libraries</span>
<span className="tb-libraries-label">{t('editor.toolbar.libraries.label')}</span>
</button>
{/* Import zip was previously hidden in a 3-dot overflow menu;
@ -842,7 +844,7 @@ export const EditorToolbar = ({
<button
onClick={() => importInputRef.current?.click()}
className="tb-btn"
title="Import a project from a .zip file"
title={t('editor.toolbar.import')}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
@ -853,7 +855,7 @@ export const EditorToolbar = ({
<button
onClick={() => handleExport()}
className="tb-btn"
title="Export the current project as a .zip file"
title={t('editor.toolbar.export')}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
@ -864,7 +866,7 @@ export const EditorToolbar = ({
<button
onClick={() => firmwareInputRef.current?.click()}
className="tb-btn"
title="Upload firmware (.hex, .bin, .elf, .ihex) to bypass compilation"
title={t('editor.toolbar.uploadFirmware')}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" />
@ -879,7 +881,7 @@ export const EditorToolbar = ({
<button
onClick={() => setConsoleOpen((v) => !v)}
className={`tb-btn tb-btn-output${consoleOpen ? ' tb-btn-output-active' : ''}`}
title="Toggle Output Console"
title={t('editor.toolbar.toggleConsole')}
>
<svg
width="18"
@ -922,7 +924,7 @@ export const EditorToolbar = ({
<line x1="12" y1="8" x2="12" y2="12" />
<line x1="12" y1="16" x2="12.01" y2="16" />
</svg>
<span>Missing library? Install it from the</span>
<span>{t('editor.toolbar.libHint.message')}</span>
<button
className="tb-lib-hint-btn"
onClick={() => {
@ -931,12 +933,12 @@ export const EditorToolbar = ({
setMissingLibHint(false);
}}
>
Library Manager
{t('editor.toolbar.libHint.cta')}
</button>
<button
className="tb-lib-hint-close"
onClick={() => setMissingLibHint(false)}
title="Dismiss"
title={t('editor.toolbar.libHint.dismiss')}
>
&times;
</button>

View File

@ -76,5 +76,38 @@
"ctaSponsors": "GitHub Sponsors",
"ctaPaypal": "Über PayPal spenden"
}
},
"editor": {
"toolbar": {
"languageMode": "Sprachmodus",
"compile": {
"addBoard": "Board hinzufügen, um zu kompilieren",
"loading": "Wird geladen…",
"loadMicropython": "MicroPython laden",
"compile": "Kompilieren (Strg+B)"
},
"run": {
"addBoard": "Board hinzufügen, um auszuführen",
"runMicropython": "MicroPython ausführen",
"run": "Ausführen (kompiliert bei Bedarf automatisch)"
},
"stop": "Stoppen",
"reset": "Zurücksetzen",
"compileAll": "Alle Boards kompilieren",
"runAll": "Alle Boards ausführen",
"libraries": {
"title": "Arduino-Bibliotheken suchen und installieren",
"label": "Bibliotheken"
},
"import": "Projekt aus einer .zip-Datei importieren",
"export": "Aktuelles Projekt als .zip exportieren",
"uploadFirmware": "Firmware (.hex, .bin, .elf, .ihex) hochladen und Kompilierung überspringen",
"toggleConsole": "Ausgabekonsole umschalten",
"libHint": {
"message": "Bibliothek fehlt? Installiere sie über den",
"cta": "Bibliotheksmanager",
"dismiss": "Schließen"
}
}
}
}

View File

@ -76,5 +76,38 @@
"ctaSponsors": "GitHub Sponsors",
"ctaPaypal": "Donate via PayPal"
}
},
"editor": {
"toolbar": {
"languageMode": "Language mode",
"compile": {
"addBoard": "Add a board to compile",
"loading": "Loading…",
"loadMicropython": "Load MicroPython",
"compile": "Compile (Ctrl+B)"
},
"run": {
"addBoard": "Add a board to run",
"runMicropython": "Run MicroPython",
"run": "Run (auto-compiles if needed)"
},
"stop": "Stop",
"reset": "Reset",
"compileAll": "Compile all boards",
"runAll": "Run all boards",
"libraries": {
"title": "Search and install Arduino libraries",
"label": "Libraries"
},
"import": "Import a project from a .zip file",
"export": "Export the current project as a .zip file",
"uploadFirmware": "Upload firmware (.hex, .bin, .elf, .ihex) to bypass compilation",
"toggleConsole": "Toggle Output Console",
"libHint": {
"message": "Missing library? Install it from the",
"cta": "Library Manager",
"dismiss": "Dismiss"
}
}
}
}

View File

@ -76,5 +76,38 @@
"ctaSponsors": "GitHub Sponsors",
"ctaPaypal": "Donar con PayPal"
}
},
"editor": {
"toolbar": {
"languageMode": "Modo de lenguaje",
"compile": {
"addBoard": "Añade una placa para compilar",
"loading": "Cargando…",
"loadMicropython": "Cargar MicroPython",
"compile": "Compilar (Ctrl+B)"
},
"run": {
"addBoard": "Añade una placa para ejecutar",
"runMicropython": "Ejecutar MicroPython",
"run": "Ejecutar (compila automáticamente si hace falta)"
},
"stop": "Detener",
"reset": "Reiniciar",
"compileAll": "Compilar todas las placas",
"runAll": "Ejecutar todas las placas",
"libraries": {
"title": "Buscar e instalar librerías de Arduino",
"label": "Librerías"
},
"import": "Importar un proyecto desde un archivo .zip",
"export": "Exportar el proyecto actual como archivo .zip",
"uploadFirmware": "Subir firmware (.hex, .bin, .elf, .ihex) para saltar la compilación",
"toggleConsole": "Mostrar/ocultar consola de salida",
"libHint": {
"message": "¿Falta una librería? Instálala desde el",
"cta": "Gestor de librerías",
"dismiss": "Descartar"
}
}
}
}

View File

@ -76,5 +76,38 @@
"ctaSponsors": "GitHub Sponsors",
"ctaPaypal": "Faire un don via PayPal"
}
},
"editor": {
"toolbar": {
"languageMode": "Mode de langage",
"compile": {
"addBoard": "Ajoutez une carte pour compiler",
"loading": "Chargement…",
"loadMicropython": "Charger MicroPython",
"compile": "Compiler (Ctrl+B)"
},
"run": {
"addBoard": "Ajoutez une carte pour exécuter",
"runMicropython": "Exécuter MicroPython",
"run": "Exécuter (compile automatiquement si besoin)"
},
"stop": "Arrêter",
"reset": "Réinitialiser",
"compileAll": "Compiler toutes les cartes",
"runAll": "Exécuter toutes les cartes",
"libraries": {
"title": "Rechercher et installer des bibliothèques Arduino",
"label": "Bibliothèques"
},
"import": "Importer un projet depuis un fichier .zip",
"export": "Exporter le projet courant en .zip",
"uploadFirmware": "Téléverser un firmware (.hex, .bin, .elf, .ihex) pour contourner la compilation",
"toggleConsole": "Afficher/masquer la console de sortie",
"libHint": {
"message": "Bibliothèque manquante ? Installez-la depuis le",
"cta": "Gestionnaire de bibliothèques",
"dismiss": "Fermer"
}
}
}
}

View File

@ -76,5 +76,38 @@
"ctaSponsors": "GitHub Sponsors",
"ctaPaypal": "Dona con PayPal"
}
},
"editor": {
"toolbar": {
"languageMode": "Modalità linguaggio",
"compile": {
"addBoard": "Aggiungi una scheda per compilare",
"loading": "Caricamento…",
"loadMicropython": "Carica MicroPython",
"compile": "Compila (Ctrl+B)"
},
"run": {
"addBoard": "Aggiungi una scheda per eseguire",
"runMicropython": "Esegui MicroPython",
"run": "Esegui (compila automaticamente se necessario)"
},
"stop": "Ferma",
"reset": "Reset",
"compileAll": "Compila tutte le schede",
"runAll": "Esegui tutte le schede",
"libraries": {
"title": "Cerca e installa librerie Arduino",
"label": "Librerie"
},
"import": "Importa un progetto da un file .zip",
"export": "Esporta il progetto corrente come file .zip",
"uploadFirmware": "Carica firmware (.hex, .bin, .elf, .ihex) per saltare la compilazione",
"toggleConsole": "Mostra/nascondi console di output",
"libHint": {
"message": "Manca una libreria? Installala dal",
"cta": "Gestore Librerie",
"dismiss": "Ignora"
}
}
}
}

View File

@ -76,5 +76,38 @@
"ctaSponsors": "GitHub Sponsors",
"ctaPaypal": "PayPal で寄付する"
}
},
"editor": {
"toolbar": {
"languageMode": "言語モード",
"compile": {
"addBoard": "コンパイルするにはボードを追加してください",
"loading": "読み込み中…",
"loadMicropython": "MicroPython を読み込む",
"compile": "コンパイル (Ctrl+B)"
},
"run": {
"addBoard": "実行するにはボードを追加してください",
"runMicropython": "MicroPython を実行",
"run": "実行(必要に応じて自動コンパイル)"
},
"stop": "停止",
"reset": "リセット",
"compileAll": "すべてのボードをコンパイル",
"runAll": "すべてのボードを実行",
"libraries": {
"title": "Arduino ライブラリを検索・インストール",
"label": "ライブラリ"
},
"import": ".zip ファイルからプロジェクトをインポート",
"export": "現在のプロジェクトを .zip としてエクスポート",
"uploadFirmware": "ファームウェア (.hex, .bin, .elf, .ihex) をアップロードしてコンパイルをスキップ",
"toggleConsole": "出力コンソールの表示切り替え",
"libHint": {
"message": "ライブラリが足りませんか?こちらからインストール:",
"cta": "ライブラリマネージャー",
"dismiss": "閉じる"
}
}
}
}

View File

@ -76,5 +76,38 @@
"ctaSponsors": "GitHub Sponsors",
"ctaPaypal": "Doar via PayPal"
}
},
"editor": {
"toolbar": {
"languageMode": "Modo de linguagem",
"compile": {
"addBoard": "Adicione uma placa para compilar",
"loading": "Carregando…",
"loadMicropython": "Carregar MicroPython",
"compile": "Compilar (Ctrl+B)"
},
"run": {
"addBoard": "Adicione uma placa para executar",
"runMicropython": "Executar MicroPython",
"run": "Executar (compila automaticamente se necessário)"
},
"stop": "Parar",
"reset": "Reiniciar",
"compileAll": "Compilar todas as placas",
"runAll": "Executar todas as placas",
"libraries": {
"title": "Buscar e instalar bibliotecas Arduino",
"label": "Bibliotecas"
},
"import": "Importar um projeto de um arquivo .zip",
"export": "Exportar o projeto atual como arquivo .zip",
"uploadFirmware": "Enviar firmware (.hex, .bin, .elf, .ihex) para pular a compilação",
"toggleConsole": "Alternar console de saída",
"libHint": {
"message": "Faltando uma biblioteca? Instale a partir do",
"cta": "Gerenciador de Bibliotecas",
"dismiss": "Dispensar"
}
}
}
}

View File

@ -76,5 +76,38 @@
"ctaSponsors": "GitHub Sponsors",
"ctaPaypal": "Пожертвовать через PayPal"
}
},
"editor": {
"toolbar": {
"languageMode": "Режим языка",
"compile": {
"addBoard": "Добавьте плату, чтобы скомпилировать",
"loading": "Загрузка…",
"loadMicropython": "Загрузить MicroPython",
"compile": "Компилировать (Ctrl+B)"
},
"run": {
"addBoard": "Добавьте плату, чтобы запустить",
"runMicropython": "Запустить MicroPython",
"run": "Запустить (при необходимости компилируется автоматически)"
},
"stop": "Остановить",
"reset": "Сбросить",
"compileAll": "Скомпилировать все платы",
"runAll": "Запустить все платы",
"libraries": {
"title": "Поиск и установка библиотек Arduino",
"label": "Библиотеки"
},
"import": "Импорт проекта из .zip",
"export": "Экспорт текущего проекта в .zip",
"uploadFirmware": "Загрузить прошивку (.hex, .bin, .elf, .ihex) и пропустить компиляцию",
"toggleConsole": "Показать/скрыть консоль вывода",
"libHint": {
"message": "Не хватает библиотеки? Установите её через",
"cta": "Менеджер библиотек",
"dismiss": "Закрыть"
}
}
}
}

View File

@ -76,5 +76,38 @@
"ctaSponsors": "GitHub Sponsors",
"ctaPaypal": "通过 PayPal 捐赠"
}
},
"editor": {
"toolbar": {
"languageMode": "语言模式",
"compile": {
"addBoard": "请先添加开发板才能编译",
"loading": "加载中…",
"loadMicropython": "加载 MicroPython",
"compile": "编译 (Ctrl+B)"
},
"run": {
"addBoard": "请先添加开发板才能运行",
"runMicropython": "运行 MicroPython",
"run": "运行(如需要会自动编译)"
},
"stop": "停止",
"reset": "重置",
"compileAll": "编译所有开发板",
"runAll": "运行所有开发板",
"libraries": {
"title": "搜索并安装 Arduino 库",
"label": "库"
},
"import": "从 .zip 文件导入项目",
"export": "将当前项目导出为 .zip 文件",
"uploadFirmware": "上传固件(.hex、.bin、.elf、.ihex以跳过编译",
"toggleConsole": "切换输出控制台",
"libHint": {
"message": "缺少库?从这里安装",
"cta": "库管理器",
"dismiss": "关闭"
}
}
}
}