fix(i18n): deep-merge locale files — shallow spread was eating sections

The common namespace was assembled with a shallow spread, so any
top-level section present in two locale files had the later file clobber
the earlier one WHOLESALE. Two live casualties:

- header: adding header.shareProject to common2 (yesterday's raw-string
  cleanup) erased common.json's whole header — header.auth.* and
  header.nav.* — so the account menu rendered "header.auth.signOut" as
  its label. My regression, caught verifying the account-menu fixes.
- editor.share.*: common2's editor section has been clobbering
  common.json's since forever — the Share modal's seven visibility
  labels were silently lost in every locale. Pre-existing.

Locale files merge by key now (deepMerge, both the synchronous en init
and the dynamic per-locale loader), which ends the failure class instead
of the instance; shareProject also moves to common.json's header where
it belonged. Verified: all header.auth/nav and editor.share leaves
resolve again in all nine locales.
This commit is contained in:
David Montero Crespo 2026-07-31 00:30:34 +02:00
parent 155513a493
commit 697a9de4f4
19 changed files with 55 additions and 42 deletions

View File

@ -30,6 +30,38 @@ import enSeo3 from "./locales/en/seo3.json";
import enSeo4 from "./locales/en/seo4.json";
import { DEFAULT_LOCALE, LOCALES, type Locale } from "./config";
/**
* Deep merge for locale resource files. The namespace used to be built
* with a SHALLOW spread, so a top-level section present in two files had
* the later file silently clobber the earlier one wholesale: common2's
* `editor` erased common.json's `editor.share.*` (the Share modal's
* visibility labels rendered as raw keys), and the same collision on
* `header` later wiped `header.auth.*` the account menu showed
* "header.auth.signOut". Merging by key ends the failure class.
*/
function deepMerge(
base: Record<string, unknown>,
extra: Record<string, unknown>,
): Record<string, unknown> {
const out: Record<string, unknown> = { ...base };
for (const [k, v] of Object.entries(extra)) {
const prev = out[k];
if (
prev && v &&
typeof prev === "object" && typeof v === "object" &&
!Array.isArray(prev) && !Array.isArray(v)
) {
out[k] = deepMerge(
prev as Record<string, unknown>,
v as Record<string, unknown>,
);
} else {
out[k] = v;
}
}
return out;
}
const NAMESPACES = ["common"] as const;
type Namespace = (typeof NAMESPACES)[number];
@ -47,9 +79,7 @@ void i18n
resources: {
en: {
common: {
...enCommon,
...enCommon2,
...enReleases,
...deepMerge(deepMerge(enCommon, enCommon2), enReleases),
seo: {
...enSeo.seo,
...enSeo2.seo,
@ -131,9 +161,10 @@ export async function loadLocale(locale: Locale): Promise<void> {
...((seo4Mod.default ?? seo4Mod).seo ?? {}),
};
const merged = {
...(commonMod.default ?? commonMod),
...(common2Mod.default ?? common2Mod),
...(releasesMod.default ?? releasesMod),
...deepMerge(
deepMerge(commonMod.default ?? commonMod, common2Mod.default ?? common2Mod),
releasesMod.default ?? releasesMod,
),
seo: seoBody,
docs: { ...docs1Body, ...docs2Body },
};

View File

@ -23,7 +23,8 @@
"signOut": "Abmelden"
},
"language": "Sprache",
"search": "Suche"
"search": "Suche",
"shareProject": "Projekt teilen"
},
"footer": {
"about": "Velxio ist ein kostenloser, quelloffener Schaltkreis- und Mikrocontroller-Simulator, der vollständig in Ihrem Browser läuft. Arduino, ESP32, RP2040 und ATtiny85, mit SPICE-genauer analoger Co-Simulation. Entwickelt für Maker, Studenten und Embedded-Ingenieure, die durch praktisches Lernen lernen. AGPLv3."

View File

@ -463,8 +463,5 @@
"subtitle": "Keine Anmeldung erforderlich. Läuft zu 100 % in Ihrem Browser. Kostenlos und Open Source.",
"openEditor": "Editor öffnen"
}
},
"header": {
"shareProject": "Projekt teilen"
}
}

View File

@ -23,7 +23,8 @@
"signOut": "Sign out"
},
"language": "Language",
"search": "Search"
"search": "Search",
"shareProject": "Share project"
},
"footer": {
"about": "Velxio is a free, open-source circuit and microcontroller simulator that runs entirely in your browser. Arduino, ESP32, RP2040 and ATtiny85, with SPICE-accurate analog co-simulation. Built for makers, students and embedded engineers learning by doing. AGPLv3."

View File

@ -465,8 +465,5 @@
"subtitle": "No signup required. Runs 100% in your browser. Free and open source.",
"openEditor": "Open Editor"
}
},
"header": {
"shareProject": "Share project"
}
}

View File

@ -23,7 +23,8 @@
"signOut": "Cerrar sesión"
},
"language": "Idioma",
"search": "Buscar"
"search": "Buscar",
"shareProject": "Compartir proyecto"
},
"footer": {
"about": "Velxio es un simulador gratuito y de código abierto de circuitos y microcontroladores que funciona completamente en tu navegador. Arduino, ESP32, RP2040 y ATtiny85, con co-simulación analógica precisa con SPICE. Creado para makers, estudiantes e ingenieros de sistemas embebidos que aprenden haciendo. AGPLv3."

View File

@ -465,8 +465,5 @@
"subtitle": "No requiere registro. Funciona 100% en tu navegador. Gratuito y de código abierto.",
"openEditor": "Abrir editor"
}
},
"header": {
"shareProject": "Compartir proyecto"
}
}

View File

@ -23,7 +23,8 @@
"signOut": "Déconnexion"
},
"language": "Langue",
"search": "Rechercher"
"search": "Rechercher",
"shareProject": "Partager le projet"
},
"footer": {
"about": "Velxio est un simulateur de circuits et microcontrôleurs gratuit et open-source qui fonctionne entièrement dans votre navigateur. Arduino, ESP32, RP2040 et ATtiny85, avec co-simulation analogique précise SPICE. Conçu pour les makers, étudiants et ingénieurs embarqués qui apprennent en pratiquant. AGPLv3."

View File

@ -463,8 +463,5 @@
"subtitle": "Aucune inscription requise. Fonctionne à 100 % dans votre navigateur. Gratuit et open source.",
"openEditor": "Ouvrir l'éditeur"
}
},
"header": {
"shareProject": "Partager le projet"
}
}

View File

@ -23,7 +23,8 @@
"signOut": "Esci"
},
"language": "Lingua",
"search": "Cerca"
"search": "Cerca",
"shareProject": "Condividi progetto"
},
"footer": {
"about": "Velxio è un simulatore gratuito e open-source di circuiti e microcontrollori che funziona interamente nel tuo browser. Arduino, ESP32, RP2040 e ATtiny85, con co-simulazione analogica SPICE accurata. Creato per maker, studenti e ingegneri embedded che imparano facendo. AGPLv3."

View File

@ -463,8 +463,5 @@
"subtitle": "Nessuna registrazione richiesta. Funziona al 100% nel tuo browser. Gratuito e open source.",
"openEditor": "Apri Editor"
}
},
"header": {
"shareProject": "Condividi progetto"
}
}

View File

@ -23,7 +23,8 @@
"signOut": "サインアウト"
},
"language": "言語",
"search": "検索"
"search": "検索",
"shareProject": "プロジェクトを共有"
},
"footer": {
"about": "Velxioは、ブラウザ上で完全に動作する無料のオープンソース回路・マイクロコントローラシミュレータです。Arduino、ESP32、RP2040、ATtiny85に対応し、SPICE精度のアナログ同時シミュレーションを提供します。メーカー、学生、組み込みエンジニアが実践的に学ぶために作られました。AGPLv3ライセンス。"

View File

@ -463,8 +463,5 @@
"subtitle": "サインアップ不要。100% ブラウザで動作。無料でオープンソース。",
"openEditor": "エディタを開く"
}
},
"header": {
"shareProject": "プロジェクトを共有"
}
}

View File

@ -23,7 +23,8 @@
"signOut": "Sair"
},
"language": "Idioma",
"search": "Pesquisar"
"search": "Pesquisar",
"shareProject": "Compartilhar projeto"
},
"footer": {
"about": "Velxio é um simulador gratuito e de código aberto de circuitos e microcontroladores que roda inteiramente no seu navegador. Arduino, ESP32, RP2040 e ATtiny85, com co-simulação analógica precisa em SPICE. Construído para makers, estudantes e engenheiros embarcados que aprendem na prática. AGPLv3."

View File

@ -463,8 +463,5 @@
"subtitle": "Sem necessidade de cadastro. Roda 100% no seu navegador. Gratuito e de código aberto.",
"openEditor": "Abrir Editor"
}
},
"header": {
"shareProject": "Compartilhar projeto"
}
}

View File

@ -23,7 +23,8 @@
"signOut": "Выйти"
},
"language": "Язык",
"search": "Поиск"
"search": "Поиск",
"shareProject": "Поделиться проектом"
},
"footer": {
"about": "Velxio — это бесплатный симулятор цепей и микроконтроллеров с открытым исходным кодом, работающий прямо в браузере. Arduino, ESP32, RP2040 и ATtiny85 с аналоговым ко-симулятором на SPICE. Создан для любителей, студентов и инженеров, изучающих встраиваемые системы на практике. AGPLv3."

View File

@ -463,8 +463,5 @@
"subtitle": "Регистрация не требуется. Работает 100% в вашем браузере. Бесплатно и с открытым исходным кодом.",
"openEditor": "Открыть редактор"
}
},
"header": {
"shareProject": "Поделиться проектом"
}
}

View File

@ -23,7 +23,8 @@
"signOut": "退出"
},
"language": "语言",
"search": "搜索"
"search": "搜索",
"shareProject": "分享项目"
},
"footer": {
"about": "Velxio 是一款免费、开源的电路和微控制器模拟器,完全在浏览器中运行。支持 Arduino、ESP32、RP2040 和 ATtiny85并具有 SPICE 精度的模拟协同仿真。专为通过实践学习的设计者、学生和嵌入式工程师打造。采用 AGPLv3 许可。"

View File

@ -463,8 +463,5 @@
"subtitle": "无需注册。100% 在浏览器中运行。免费且开源。",
"openEditor": "打开编辑器"
}
},
"header": {
"shareProject": "分享项目"
}
}