feat(i18n): translate the whole interface

Mark every UI string the unmarked-text check reported (534) plus text it
cannot see (helpers, joined labels, runtime-built panels), and translate
the result to Spanish and Russian: 1,679 messages each.

- Kept on purpose, with the reason where the text lives: provider and
  product names, place and camera names, codes and units, dB values, the HUD
  terminal readouts, demo shot titles that saved projects look up by title,
  and text for AI tools and the voice model.
- Modules shared with the server or AI tools stay free of the i18n import
  (local msg); the wind reading and voice session stay English and are
  translated where the page shows them.
- npm test now runs the unmarked-text check.
- Fixes on the way: a duplicated radio privacy paragraph, the contact panel
  toggle saying Expand while open, the CSS filter mistaking & for CSS.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
German KhokhlovandClaude Opus 5.5 committed 2026-10-12 19:24:42 +04:00
1 parent ee72133574
commit 3129e531e6
99 files changed
+4670 -1294

No files matched your search

+36 -7
View File
@@ -4,11 +4,12 @@
*/
import { expandNepalEvidencePack } from './nepalEvidencePack.js';
import { msg } from '../i18n/index.js';
const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
id: 'bhote-koshi-nepal-evidence-pack',
version: 12,
title: 'Bhote Koshi Evidence Sequence',
title: msg('Bhote Koshi Evidence Sequence'),
style: 'normal',
ui: { hidePanels: false, hudMode: 'full', safeFrame: '16:9' },
layers: {
@@ -26,6 +27,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
fromShotTitles: ['Shot 1', 'Shot 2', 'Shot 3'],
cameraPath: [
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Global Incident Context',
lat: 27.5962,
lon: 78.5718,
@@ -43,6 +45,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Nepal-Focused Globe Rotation',
lat: 28.7248,
lon: 81.3226,
@@ -60,6 +63,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bhote Koshi Regional Approach',
lat: 27.0354,
lon: 84.6287,
@@ -77,6 +81,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bhote Koshi Nearby Cities',
lat: 27.891,
lon: 85.428,
@@ -94,6 +99,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bhote Koshi Incident Corridor',
lat: 28.0529,
lon: 85.2189,
@@ -111,6 +117,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bhote Koshi Flood Path',
lat: 28.1691,
lon: 85.352,
@@ -128,6 +135,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bhote Koshi Corridor Overview',
lat: 27.8986,
lon: 84.8723,
@@ -145,6 +153,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bhote Koshi Upper Valley',
lat: 28.4187,
lon: 85.4341,
@@ -221,6 +230,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
shotPatches: [
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Global Incident Context',
visual: { mapStack: 'photoreal' },
layers: {
@@ -236,6 +246,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Nepal-Focused Globe Rotation',
visual: { mapStack: 'photoreal' },
layers: {
@@ -251,6 +262,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bhote Koshi Regional Approach',
visual: { mapStack: 'photoreal' },
layers: {
@@ -266,6 +278,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bhote Koshi Nearby Cities',
visual: { mapStack: 'photoreal' },
layers: {
@@ -281,6 +294,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bhote Koshi Incident Corridor',
camera: {
lat: 28.0529,
@@ -305,6 +319,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bhote Koshi Flood Path',
visual: { mapStack: 'photoreal' },
layers: {
@@ -320,6 +335,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bhote Koshi Corridor Overview',
visual: { mapStack: 'photoreal' },
layers: {
@@ -335,6 +351,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bhote Koshi Upper Valley',
holdSec: 8,
visual: { mapStack: 'photoreal' },
@@ -357,6 +374,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Upper Valley Collapse',
camera: {
lat: 28.417,
@@ -380,24 +398,29 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Nepal-China Border Gate',
visual: { mapStack: 'photoreal' },
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Timure Evidence Cluster',
visual: { mapStack: 'photoreal' },
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Syabru Besi Passage',
visual: { mapStack: 'photoreal' },
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bidur / Trishuli Consequence',
visual: { mapStack: 'photoreal' },
},
],
cameraPath: [
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Upper Valley Collapse',
lat: 28.417,
lon: 85.3937,
@@ -421,6 +444,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Debris-Dammed Lake',
lat: 28.392914,
lon: 85.570921,
@@ -444,6 +468,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Nepal-China Border Gate',
mapStack: 'photoreal',
lat: 28.316789,
@@ -474,6 +499,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Timure Evidence Cluster',
mapStack: 'photoreal',
lat: 28.285968,
@@ -502,6 +528,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Syabru Besi Passage',
mapStack: 'photoreal',
lat: 28.210306,
@@ -530,6 +557,7 @@ const BHOTE_KOSHI_NEPAL_BASE_RECIPE = Object.freeze({
},
},
{
// i18n-ignore: shot title, matched by title when the recipe upgrades a saved project
title: 'Bidur / Trishuli Consequence',
mapStack: 'photoreal',
lat: 27.981737,
@@ -569,7 +597,7 @@ const BHOTE_KOSHI_NEPAL_APPEND_RECIPE = BHOTE_KOSHI_NEPAL_BASE_RECIPE
const BHOTE_KOSHI_NEPAL_BOOTSTRAP_RECIPE = BHOTE_KOSHI_NEPAL_APPEND_RECIPE
? Object.freeze({
id: 'bhote-koshi-nepal-scene',
title: 'Nepal Flood Incident',
title: msg('Nepal Flood Incident'),
durationSec: 15,
style: BHOTE_KOSHI_NEPAL_APPEND_RECIPE.style,
ui: BHOTE_KOSHI_NEPAL_APPEND_RECIPE.ui,
@@ -583,6 +611,7 @@ const BHOTE_KOSHI_NEPAL_BOOTSTRAP_RECIPE = BHOTE_KOSHI_NEPAL_APPEND_RECIPE
.slice(0, 3)
.map((keyframe, index) => ({
...keyframe,
// i18n-ignore: legacy shot titles the bootstrap matches verbatim
title: `Shot ${index + 1}`,
})),
})
@@ -593,7 +622,7 @@ const EVENT_RECIPES = [BHOTE_KOSHI_NEPAL_BOOTSTRAP_RECIPE].filter(Boolean);
const PUBLIC_SCENE_RECIPES = [
{
id: 'flights-radar',
title: 'Global Flights Radar',
title: msg('Global Flights Radar'),
durationSec: 30,
style: 'retro',
ui: { hidePanels: true, hudMode: 'minimal', safeFrame: '16:9' },
@@ -663,7 +692,7 @@ const PUBLIC_SCENE_RECIPES = [
},
{
id: 'orbital-watch',
title: 'Orbital Watch',
title: msg('Orbital Watch'),
durationSec: 32,
style: 'surveillance',
ui: { hidePanels: true, hudMode: 'full', safeFrame: '16:9' },
@@ -741,7 +770,7 @@ const PUBLIC_SCENE_RECIPES = [
},
{
id: 'thermal-threats',
title: 'Thermal Threat Board',
title: msg('Thermal Threat Board'),
durationSec: 26,
style: 'thermal',
ui: { hidePanels: true, hudMode: 'full', safeFrame: '16:9' },
@@ -809,7 +838,7 @@ const PUBLIC_SCENE_RECIPES = [
},
{
id: 'city-overload',
title: 'City Overload',
title: msg('City Overload'),
durationSec: 30,
style: 'surveillance',
ui: { hidePanels: true, hudMode: 'minimal', safeFrame: '9:16' },
@@ -887,7 +916,7 @@ const PUBLIC_SCENE_RECIPES = [
},
{
id: 'omniscience-pullback',
title: 'Omniscience Pullback',
title: msg('Omniscience Pullback'),
durationSec: 36,
style: 'retro',
ui: { hidePanels: true, hudMode: 'full', safeFrame: '16:9' },