feat(i18n): ship Spanish

Register es next to ru (selector shows EN | ES | RU) and complete the
catalog against the current English: the 13 messages added since #602,
the "many" plural form Intl.PluralRules('es') selects for exact millions,
and fixes where the English had changed (e.g. "hace hace" in LIVE ·
updated, minutes written as metres). Terminology made consistent (buque,
aeronave, incendio activo); key names stay in English. Meir's wording is
kept everywhere else. Adds docs/translations/es.md.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
German KhokhlovandClaude Opus 5.5 committed 2026-10-12 14:33:43 +04:00
1 parent 47cfdb823e
commit 70936b58b9
9 files changed
+180 -51

No files matched your search

+4 -1
View File
@@ -1,9 +1,12 @@
# Changelog # Changelog
- Spanish interface (`es`), translated by @meirm (#602) and reviewed against the
current English.
- Interface localization, starting with Russian. UI text is marked with - Interface localization, starting with Russian. UI text is marked with
`t()`, `tn()` (plurals) and `msg()` in code and `data-i18n*` in markup, keyed `t()`, `tn()` (plurals) and `msg()` in code and `data-i18n*` in markup, keyed
by the English text itself; each language is one flat JSON catalog by the English text itself; each language is one flat JSON catalog
(`src/i18n/locales/ru.json`). The language comes from `?lang=`, the EN/RU (`src/i18n/locales/ru.json`). The language comes from `?lang=`, the language
switch in the Visual Presets dock, then the browser language; English stays switch in the Visual Presets dock, then the browser language; English stays
the default and the fallback. `npm run i18n`, also run by `npm test`, fails on the default and the fallback. `npm run i18n`, also run by `npm test`, fails on
missing, unused or broken translations. Built on the i18n foundation by missing, unused or broken translations. Built on the i18n foundation by
+2 -2
View File
@@ -3011,7 +3011,7 @@ test:track` 43 tracking invariants · headless QA harnesses under
### Interface localization (October 2026) ### Interface localization (October 2026)
Shipped locales: **en** (source and fallback) and **ru**. The code lives in Shipped locales: **en** (source and fallback), **es** and **ru**. The code lives in
`src/i18n/`. How to mark UI text: [`docs/I18N.md`](./I18N.md); translator workflow: `src/i18n/`. How to mark UI text: [`docs/I18N.md`](./I18N.md); translator workflow:
[`docs/TRANSLATORS.md`](./TRANSLATORS.md). [`docs/TRANSLATORS.md`](./TRANSLATORS.md).
@@ -3022,7 +3022,7 @@ Shipped locales: **en** (source and fallback) and **ru**. The code lives in
value). English has no catalog; every other locale is value). English has no catalog; every other locale is
`src/i18n/locales/<code>.json`, and a missing entry falls back to English. `src/i18n/locales/<code>.json`, and a missing entry falls back to English.
- **Locale choice.** `?lang=` (one-shot) → stored choice (`gev:locale:v1`) → - **Locale choice.** `?lang=` (one-shot) → stored choice (`gev:locale:v1`) →
`navigator.languages` → English. The EN/RU switch in the Visual Presets dock `navigator.languages` → English. The language switch in the Visual Presets dock
stores the choice and reloads, so nothing re-renders live. stores the choice and reloads, so nothing re-renders live.
- **Gate.** `npm run i18n` (and `src/i18n/catalog.test.mjs` under `npm test`) - **Gate.** `npm run i18n` (and `src/i18n/catalog.test.mjs` under `npm test`)
extracts every message and fails on missing, unused, placeholder-mismatched or extracts every message and fails on missing, unused, placeholder-mismatched or
+1 -1
View File
@@ -56,7 +56,7 @@ npm run i18n -- --prune # drop entries whose English no longer exists
Changing the English changes the key, so the old translation goes unused and the new text shows as missing. Add the translation to `src/i18n/locales/ru.json` (or ask a translator), prune, and run `npm test`, which runs the same check and fails until every language is complete. Changing the English changes the key, so the old translation goes unused and the new text shows as missing. Add the translation to `src/i18n/locales/ru.json` (or ask a translator), prune, and run `npm test`, which runs the same check and fails until every language is complete.
To see a language, open the app with `?lang=ru`, or use the EN/RU switch in the Visual Presets dock. To see a language, open the app with `?lang=ru`, or use the language switch in the Visual Presets dock.
## Where things live ## Where things live
+3 -3
View File
@@ -1,6 +1,6 @@
# Translating God's Eye View # Translating God's Eye View
Shipped languages: **English** (source and fallback) and **Russian** (`ru`). Shipped languages: **English** (source and fallback), **Spanish** (`es`) and **Russian** (`ru`).
## How it works ## How it works
@@ -22,7 +22,7 @@ Every other language is one flat JSON file, `src/i18n/locales/<code>.json`, keye
A `tn()` entry is keyed by the English plural form and holds one string per `Intl.PluralRules` category of that language. A missing entry falls back to English. A `tn()` entry is keyed by the English plural form and holds one string per `Intl.PluralRules` category of that language. A missing entry falls back to English.
The page picks its language from `?lang=`, then the choice stored by the EN/RU switch in the Visual Presets dock, then the browser languages, then English. Switching reloads the page. The page picks its language from `?lang=`, then the choice stored by the language switch in the Visual Presets dock, then the browser languages, then English. Switching reloads the page.
## The check ## The check
@@ -63,4 +63,4 @@ These are contracts, not copy: layer ids and registry keys, status enums and oth
## Language notes ## Language notes
Each language keeps its glossary, plural forms, units and style in its own file, `docs/translations/<code>.md`: [Russian](./translations/ru.md). Read it before translating, and add a term there when you settle on one. Each language keeps its glossary, plural forms, units and style in its own file, `docs/translations/<code>.md`: [Spanish](./translations/es.md), [Russian](./translations/ru.md). Read it before translating, and add a term there when you settle on one.
+70
View File
@@ -0,0 +1,70 @@
# Spanish (`es`)
Catalog: `src/i18n/locales/es.json`. General rules: [TRANSLATORS.md](../TRANSLATORS.md).
## Style
- Neutral Spanish that reads naturally in Spain and Latin America; avoid regionalisms.
- Address the user with informal "tú" imperatives: «Añade», «Activa», «Elige», «Pega», «Inténtalo de nuevo». Tooltips that name an action may use the infinitive: «Expandir el panel», «Restablecer la cámara».
- Sentence case, not Title Case: "Live Flights" → «Vuelos en vivo». UPPERCASE English stays UPPERCASE: «EN VIVO», «SIN DATOS».
- Quotes inside Spanish text are straight double quotes: «¿Eliminar el plano "{shot}"?». Questions and exclamations open with ¿ and ¡.
- Short labels, chips and HUD readouts stay short. A standard abbreviation with a period beats a wrapped line: ANT., SIG., VEL., DIST., SINCR., cám., cob.
- The HUD codes HDG, BRG, CRS, FOV, DEST, SPD, RANGE and ALT stay in English everywhere, as in cockpit avionics. Words used in a sentence are translated: heading → «rumbo», range → «alcance».
- Keyboard keys stay in English: Space, Esc, Enter, Tab, Shift, H, 1–9 («Mantén pulsado Space para hablar»).
- Units: km, m, km/h, m/s, kn (knots), ft (feet), h, min, s; in UPPERCASE text KM, KM/S, KN, FT, MIN, H. "m" is always metres, so minutes are «min» («hace 5 min»). MW stays MW. `°` and `%` stay.
- "ago" goes before the time: «hace {count} min». When a placeholder already holds a localized "ago" text (`{age}`, `{ago}`), do not add «hace» again.
- Spelling: «costo» (not «coste»).
## Plurals
A `tn()` entry needs three forms. `Intl.PluralRules('es')` picks:
| Form | Counts | Example |
| ------- | -------------------------------------- | -------------------- |
| `one` | 1 | 1 cámara |
| `many` | 1 000 000, 2 000 000… (exact millions) | 1 000 000 de cámaras |
| `other` | everything else: 0, 2–999 999, 1.5… | 3 cámaras |
The `many` form is the `other` text with «de» after the number: «{count} de cámaras cargadas», «{count} DE CLAVES EN ESPERA».
## Glossary
| English | Español |
| --------------------------------------------- | ----------------------------------------------------------------- |
| layer / data layer | capa / capa de datos |
| feed / source / data source | fuente / fuente / fuente de datos |
| LIVE (status) / live data | EN VIVO / datos en vivo |
| SIMULATED | SIMULADO |
| stale / degraded / unavailable | desactualizado / degradado / no disponible |
| retry / retrying | reintento / reintentando |
| key (API key) / POWER UP / POWERED UP | clave / ENCENDER / ENCENDIDO |
| Provider Settings | Ajustes de proveedores |
| ON / OFF (state chips) | ACTIVADO / DESACTIVADO |
| enable / disable | activar / desactivar |
| globe / map / map source / map stack | globo / mapa / fuente del mapa / conjunto de mapas |
| aircraft, plane / flight / military flights | aeronave / vuelo / vuelos militares |
| vessel, ship | buque |
| satellite / shell (Starlink) / DENSE | satélite / capa / DENSO |
| launch (rocket) / launch site / space mission | lanzamiento / lugar de lanzamiento / misión espacial |
| ascent / replay / payload / stage | ascenso / repetición / carga útil / etapa |
| contact / tracking | contacto / rastreo |
| installation / site | instalación / sitio |
| mapped / observed | mapeado / observado |
| camera / CCTV camera | cámara / cámara CCTV |
| earthquake / active fire | terremoto / incendio activo |
| radio station | emisora |
| road / flow (traffic) | vía / flujo |
| scene / shot / scene recipe | escena / plano / receta de escena |
| briefing / panel / dock | información / panel / dock |
| cockpit | cabina |
| preset / visual preset | preajuste / preajuste visual |
| Scope (circular viewport mask) / keyhole | mirilla / ojo de cerradura |
| feather / fade | difuminado / desvanecimiento |
| detection overlay | superposición de detección |
| heading, course / altitude / ground speed | rumbo / altitud / velocidad respecto al suelo (short: VEL. SUELO) |
| HDG / BRG / CRS / FOV / DEST / SPD / RANGE | HDG / BRG / CRS / FOV / DEST / SPD / RANGE (unchanged) |
| PREV / NEXT | ANT. / SIG. |
| Previous / Next (button text) | Anterior / Siguiente |
| L / R (relative bearing) | I / D |
| NOT AN ALL-CLEAR | NO IMPLICA TODO DESPEJADO |
| click / click to … | haz clic / clic para … |
+31
View File
@@ -421,6 +421,7 @@
"src/localRequestGate.mjs", "src/localRequestGate.mjs",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": [] "external": []
@@ -445,6 +446,7 @@
"src/data/layerSnapshot.js", "src/data/layerSnapshot.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": [] "external": []
@@ -459,6 +461,7 @@
"src/app/stateChannel.js", "src/app/stateChannel.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": [] "external": []
@@ -473,6 +476,7 @@
"src/ui/radioTunerModel.js", "src/ui/radioTunerModel.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": [] "external": []
@@ -489,6 +493,7 @@
"src/ui/cctvPresentation.js", "src/ui/cctvPresentation.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": [] "external": []
@@ -510,6 +515,7 @@
"src/ui/panelRailGeometry.js", "src/ui/panelRailGeometry.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": [] "external": []
@@ -541,6 +547,7 @@
"src/ui/panelRailGeometry.js", "src/ui/panelRailGeometry.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -553,6 +560,7 @@
"src/ui/scenePresentation.js", "src/ui/scenePresentation.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": [] "external": []
@@ -695,6 +703,7 @@
"src/data/cameraArrival.js", "src/data/cameraArrival.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -804,6 +813,7 @@
"src/data/cameraArrival.js", "src/data/cameraArrival.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -861,6 +871,7 @@
"src/data/modelEligibility.js", "src/data/modelEligibility.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -903,6 +914,7 @@
"src/data/modelEligibility.js", "src/data/modelEligibility.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -959,6 +971,7 @@
"src/data/inputOwnership.js", "src/data/inputOwnership.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -1008,6 +1021,7 @@
"src/data/inputOwnership.js", "src/data/inputOwnership.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -1037,6 +1051,7 @@
"src/data/inputOwnership.js", "src/data/inputOwnership.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium", "satellite.js"] "external": ["cesium", "satellite.js"]
@@ -1067,6 +1082,7 @@
"src/data/inputOwnership.js", "src/data/inputOwnership.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -1105,6 +1121,7 @@
"src/data/infrastructureOverlayEntry.js", "src/data/infrastructureOverlayEntry.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium", "@mapbox/vector-tile", "pbf"] "external": ["cesium", "@mapbox/vector-tile", "pbf"]
@@ -1135,6 +1152,7 @@
"src/ui/panelRailGeometry.js", "src/ui/panelRailGeometry.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -1179,6 +1197,7 @@
"src/layers/traffic/roadModes.js", "src/layers/traffic/roadModes.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium", "pbf", "@mapbox/vector-tile"] "external": ["cesium", "pbf", "@mapbox/vector-tile"]
@@ -1205,6 +1224,7 @@
"src/data/cameraSensitivity.js", "src/data/cameraSensitivity.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -1249,6 +1269,7 @@
"src/layers/cctv/sourcePolicy.js", "src/layers/cctv/sourcePolicy.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["hls.js", "cesium"] "external": ["hls.js", "cesium"]
@@ -1347,6 +1368,7 @@
"src/data/inputOwnership.js", "src/data/inputOwnership.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -1367,6 +1389,7 @@
"src/data/inputOwnership.js", "src/data/inputOwnership.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -1419,6 +1442,7 @@
"src/maps/imageryHost.js", "src/maps/imageryHost.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -1469,6 +1493,7 @@
"src/voice/pointerReticle.js", "src/voice/pointerReticle.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": [] "external": []
@@ -2276,6 +2301,7 @@
"src/app/embed.js", "src/app/embed.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": [ "external": [
@@ -2801,6 +2827,7 @@
"src/sources/infrastructureData.js", "src/sources/infrastructureData.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": [ "external": [
@@ -2906,6 +2933,7 @@
"src/ui/uiLifetime.js", "src/ui/uiLifetime.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": [] "external": []
@@ -2937,6 +2965,7 @@
"src/ui/visualSettings.js", "src/ui/visualSettings.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": ["cesium"] "external": ["cesium"]
@@ -2960,6 +2989,7 @@
"src/ui/uiLifetime.js", "src/ui/uiLifetime.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": [] "external": []
@@ -3086,6 +3116,7 @@
"src/voice/pointerReticle.js", "src/voice/pointerReticle.js",
"src/i18n/index.js", "src/i18n/index.js",
"src/i18n/locale.js", "src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json" "src/i18n/locales/ru.json"
], ],
"external": [] "external": []
+2 -1
View File
@@ -15,9 +15,10 @@ import {
normalizeLocale, normalizeLocale,
writeStoredLocale, writeStoredLocale,
} from './locale.js'; } from './locale.js';
import es from './locales/es.json' with { type: 'json' };
import ru from './locales/ru.json' with { type: 'json' }; import ru from './locales/ru.json' with { type: 'json' };
const CATALOGS = Object.freeze({ ru }); const CATALOGS = Object.freeze({ es, ru });
let currentLocale = DEFAULT_LOCALE; let currentLocale = DEFAULT_LOCALE;
+6 -2
View File
@@ -11,10 +11,14 @@ export const DEFAULT_LOCALE = 'en';
* Shipped locales, in selector order. Adding one: locales/<code>.json, an * Shipped locales, in selector order. Adding one: locales/<code>.json, an
* import in index.js, and an entry here (see docs/TRANSLATORS.md). * import in index.js, and an entry here (see docs/TRANSLATORS.md).
*/ */
export const LOCALES = Object.freeze(['en', 'ru']); export const LOCALES = Object.freeze(['en', 'es', 'ru']);
/** Each locale named in its own language, for the selector. */ /** Each locale named in its own language, for the selector. */
export const LOCALE_NAMES = Object.freeze({ en: 'English', ru: 'Русский' }); export const LOCALE_NAMES = Object.freeze({
en: 'English',
es: 'Español',
ru: 'Русский',
});
/** Right-to-left locales. */ /** Right-to-left locales. */
const RTL_LOCALES = Object.freeze([]); const RTL_LOCALES = Object.freeze([]);
+61 -41
View File
@@ -123,14 +123,14 @@
"LIVE TRACK · COURSE ALIGNED": "RASTREO EN VIVO · RUMBO ALINEADO", "LIVE TRACK · COURSE ALIGNED": "RASTREO EN VIVO · RUMBO ALINEADO",
"Cockpit vision style": "Estilo de visión de la cabina", "Cockpit vision style": "Estilo de visión de la cabina",
"Current aircraft heading": "Rumbo actual de la aeronave", "Current aircraft heading": "Rumbo actual de la aeronave",
"GROUND SPEED · KTS": "VEL. SUELO · KTS", "GROUND SPEED · KTS": "VEL. SUELO · KN",
"ALTITUDE · FT": "ALTITUD · FT", "ALTITUDE · FT": "ALTITUD · FT",
"PREV": "ANT", "PREV": "ANT.",
"Previous cockpit vision style": "Estilo de visión de cabina anterior", "Previous cockpit vision style": "Estilo de visión de cabina anterior",
"Previous vision style": "Estilo de visión anterior", "Previous vision style": "Estilo de visión anterior",
"Current cockpit vision style: NORMAL. Activate for next style.": "Estilo de visión de cabina actual: NORMAL. Actívalo para pasar al siguiente estilo.", "Current cockpit vision style: NORMAL. Activate for next style.": "Estilo de visión de cabina actual: NORMAL. Actívalo para pasar al siguiente estilo.",
"Current style: NORMAL — click for next": "Estilo actual: NORMAL — haz clic para el siguiente", "Current style: NORMAL — click for next": "Estilo actual: NORMAL — haz clic para el siguiente",
"NEXT": "SIG", "NEXT": "SIG.",
"Next cockpit vision style": "Siguiente estilo de visión de cabina", "Next cockpit vision style": "Siguiente estilo de visión de cabina",
"Next vision style": "Siguiente estilo de visión", "Next vision style": "Siguiente estilo de visión",
"View switcher": "Selector de vistas", "View switcher": "Selector de vistas",
@@ -180,7 +180,7 @@
"Expand panel": "Expandir panel", "Expand panel": "Expandir panel",
"Context mode": "Modo de contexto", "Context mode": "Modo de contexto",
"CONTACTS": "CONTACTOS", "CONTACTS": "CONTACTOS",
"Cycles the nearest contacts of whatever type you select — planes, vessels, installations. Satellites track independently.": "Ronda por los contactos más cercanos del tipo que elijas — aeronaves, embarcaciones, instalaciones. Los satélites se rastrean por separado.", "Cycles the nearest contacts of whatever type you select — planes, vessels, installations. Satellites track independently.": "Recorre los contactos más cercanos del tipo que elijas — aeronaves, buques, instalaciones. Los satélites se rastrean por separado.",
"SPACE MISSIONS": "MISIONES ESPACIALES", "SPACE MISSIONS": "MISIONES ESPACIALES",
"SELECT CONTEXT": "SELECCIONAR CONTEXTO", "SELECT CONTEXT": "SELECCIONAR CONTEXTO",
"Contact Context actions": "Acciones de contexto de contacto", "Contact Context actions": "Acciones de contexto de contacto",
@@ -243,6 +243,7 @@
"DISTANCE UNKNOWN": "DISTANCIA DESCONOCIDA", "DISTANCE UNKNOWN": "DISTANCIA DESCONOCIDA",
"{count} INPUTS UNKNOWN": { "{count} INPUTS UNKNOWN": {
"one": "{count} DATO DESCONOCIDO", "one": "{count} DATO DESCONOCIDO",
"many": "{count} DE DATOS DESCONOCIDOS",
"other": "{count} DATOS DESCONOCIDOS" "other": "{count} DATOS DESCONOCIDOS"
}, },
"SOURCE STATUS UNAVAILABLE": "ESTADO DE FUENTE NO DISPONIBLE", "SOURCE STATUS UNAVAILABLE": "ESTADO DE FUENTE NO DISPONIBLE",
@@ -259,6 +260,7 @@
"CONTACT LOST · LAST KNOWN READOUT · NOT AN ALL-CLEAR": "CONTACTO PERDIDO · ÚLTIMA LECTURA CONOCIDA · NO IMPLICA TODO DESPEJADO", "CONTACT LOST · LAST KNOWN READOUT · NOT AN ALL-CLEAR": "CONTACTO PERDIDO · ÚLTIMA LECTURA CONOCIDA · NO IMPLICA TODO DESPEJADO",
"{count} INPUTS UNKNOWN · NOT AN ALL-CLEAR": { "{count} INPUTS UNKNOWN · NOT AN ALL-CLEAR": {
"one": "{count} DATO DESCONOCIDO · NO IMPLICA TODO DESPEJADO", "one": "{count} DATO DESCONOCIDO · NO IMPLICA TODO DESPEJADO",
"many": "{count} DE DATOS DESCONOCIDOS · NO IMPLICA TODO DESPEJADO",
"other": "{count} DATOS DESCONOCIDOS · NO IMPLICA TODO DESPEJADO" "other": "{count} DATOS DESCONOCIDOS · NO IMPLICA TODO DESPEJADO"
}, },
"AVAILABLE INPUTS CURRENT · NOT AN ALL-CLEAR": "DATOS DISPONIBLES ACTUALIZADOS · NO IMPLICA TODO DESPEJADO", "AVAILABLE INPUTS CURRENT · NOT AN ALL-CLEAR": "DATOS DISPONIBLES ACTUALIZADOS · NO IMPLICA TODO DESPEJADO",
@@ -288,7 +290,7 @@
"{domain} · {age}": "{domain} · {age}", "{domain} · {age}": "{domain} · {age}",
"{source} · LOCATION QUERY": "{source} · CONSULTA POR UBICACIÓN", "{source} · LOCATION QUERY": "{source} · CONSULTA POR UBICACIÓN",
"TIME UNKNOWN": "HORA DESCONOCIDA", "TIME UNKNOWN": "HORA DESCONOCIDA",
"{count}M AGO": "HACE {count} M", "{count}M AGO": "HACE {count} MIN",
"{count}H AGO": "HACE {count} H", "{count}H AGO": "HACE {count} H",
"{count}D AGO": "HACE {count} D", "{count}D AGO": "HACE {count} D",
"DIR UNKNOWN": "DIR DESCONOCIDA", "DIR UNKNOWN": "DIR DESCONOCIDA",
@@ -304,7 +306,7 @@
"Selected data layers could not be cleared": "No se pudieron limpiar las capas de datos seleccionadas", "Selected data layers could not be cleared": "No se pudieron limpiar las capas de datos seleccionadas",
"ACQUIRING": "OBTENIENDO", "ACQUIRING": "OBTENIENDO",
"entity": "entidad", "entity": "entidad",
"SHARED {subject}": "{subject} COMPARTIDA", "SHARED {subject}": "{subject} COMPARTIDO",
"Shared {subject} follow expired": "El seguimiento de {subject} compartido ha caducado", "Shared {subject} follow expired": "El seguimiento de {subject} compartido ha caducado",
"Shared {subject} could not be restored — feed unavailable": "No se pudo restaurar {subject} compartido — fuente no disponible", "Shared {subject} could not be restored — feed unavailable": "No se pudo restaurar {subject} compartido — fuente no disponible",
"Shared {subject} is unavailable": "{subject} compartido no está disponible", "Shared {subject} is unavailable": "{subject} compartido no está disponible",
@@ -318,7 +320,7 @@
"Zoom in to search mapped installations": "Haz zoom para buscar instalaciones mapeadas", "Zoom in to search mapped installations": "Haz zoom para buscar instalaciones mapeadas",
"Nearby installations refreshed": "Instalaciones cercanas actualizadas", "Nearby installations refreshed": "Instalaciones cercanas actualizadas",
"That layer is unavailable in the current Context mode": "Esa capa no está disponible en el modo de contexto actual", "That layer is unavailable in the current Context mode": "Esa capa no está disponible en el modo de contexto actual",
"start": "iniciar", "start": "iniciarse",
"stop": "detenerse", "stop": "detenerse",
"{layerId} could not {action} cleanly": "{layerId} no pudo {action} correctamente", "{layerId} could not {action} cleanly": "{layerId} no pudo {action} correctamente",
"Radio could not {action} cleanly": "Radio no pudo {action} correctamente", "Radio could not {action} cleanly": "Radio no pudo {action} correctamente",
@@ -327,7 +329,7 @@
"CCTV calibration reset": "Calibración de CCTV restablecida", "CCTV calibration reset": "Calibración de CCTV restablecida",
"CCTV layer unavailable": "Capa de CCTV no disponible", "CCTV layer unavailable": "Capa de CCTV no disponible",
"MAP": "MAPA", "MAP": "MAPA",
"CONTACTS — nearest planes · vessels · sites": "CONTACTOS — aeronaves · embarcaciones · sitios más cercanos", "CONTACTS — nearest planes · vessels · sites": "CONTACTOS — aeronaves · buques · sitios más cercanos",
"SPACE MISSIONS — launches & orbital assets": "MISIONES ESPACIALES — lanzamientos y activos orbitales", "SPACE MISSIONS — launches & orbital assets": "MISIONES ESPACIALES — lanzamientos y activos orbitales",
"Space Missions cancellation could not restore the previous layer state": "La cancelación de Misiones espaciales no pudo restaurar el estado previo de las capas", "Space Missions cancellation could not restore the previous layer state": "La cancelación de Misiones espaciales no pudo restaurar el estado previo de las capas",
"Collapse Cockpit display options": "Contraer las opciones de visualización de la cabina", "Collapse Cockpit display options": "Contraer las opciones de visualización de la cabina",
@@ -348,7 +350,7 @@
"SYNCING DIRECTORY": "SINCRONIZANDO DIRECTORIO", "SYNCING DIRECTORY": "SINCRONIZANDO DIRECTORIO",
"SYNCING": "SINCRONIZANDO", "SYNCING": "SINCRONIZANDO",
"station": "emisora", "station": "emisora",
"Ready": "Lista", "Ready": "Listo",
"VIEWSHED ON": "ÁREA VISIBLE ACTIVADA", "VIEWSHED ON": "ÁREA VISIBLE ACTIVADA",
"FRAME · LOADING": "FOTOGRAMA · CARGANDO", "FRAME · LOADING": "FOTOGRAMA · CARGANDO",
"FRAME · UNAVAILABLE": "FOTOGRAMA · NO DISPONIBLE", "FRAME · UNAVAILABLE": "FOTOGRAMA · NO DISPONIBLE",
@@ -358,13 +360,15 @@
"CURATED": "CURADA", "CURATED": "CURADA",
"RAW PRIOR": "PREVIA SIN PROCESAR", "RAW PRIOR": "PREVIA SIN PROCESAR",
"MONITOR": "MONITOR", "MONITOR": "MONITOR",
"{city} · HDG {heading} · FOV {fov} · RANGE {range}m · {projection}{calBadge} · {provider}{status}": "{city} · HDG {heading} · FOV {fov} · ALCANCE {range}m · {projection}{calBadge} · {provider}{status}", "{city} · HDG {heading} · FOV {fov} · RANGE {range}m · {projection}{calBadge} · {provider}{status}": "{city} · HDG {heading} · FOV {fov} · RANGE {range}m · {projection}{calBadge} · {provider}{status}",
"{count} cameras loaded · click a camera to activate": { "{count} cameras loaded · click a camera to activate": {
"one": "{count} cámara cargada · haz clic en una cámara para activarla", "one": "{count} cámara cargada · haz clic en una cámara para activarla",
"many": "{count} de cámaras cargadas · haz clic en una cámara para activarla",
"other": "{count} cámaras cargadas · haz clic en una cámara para activarla" "other": "{count} cámaras cargadas · haz clic en una cámara para activarla"
}, },
"{count} cameras loaded · enable CCTV to activate": { "{count} cameras loaded · enable CCTV to activate": {
"one": "{count} cámara cargada · activa CCTV para activarla", "one": "{count} cámara cargada · activa CCTV para activarla",
"many": "{count} de cámaras cargadas · activa CCTV para activarlas",
"other": "{count} cámaras cargadas · activa CCTV para activarlas" "other": "{count} cámaras cargadas · activa CCTV para activarlas"
}, },
"No summary available.": "No hay resumen disponible.", "No summary available.": "No hay resumen disponible.",
@@ -373,14 +377,14 @@
"Detection overlay: off": "Superposición de detección: desactivada", "Detection overlay: off": "Superposición de detección: desactivada",
"SPARSE": "DISPERSA", "SPARSE": "DISPERSA",
"BALANCED": "EQUILIBRADA", "BALANCED": "EQUILIBRADA",
"DENSE": "DENSA", "DENSE": "DENSO",
"Resetting to full globe view": "Restableciendo la vista de globo completo", "Resetting to full globe view": "Restableciendo la vista de globo completo",
"Resetting cockpit to full globe view": "Restableciendo la cabina a la vista de globo completo", "Resetting cockpit to full globe view": "Restableciendo la cabina a la vista de globo completo",
"ORBIT": "ÓRBITA", "ORBIT": "ÓRBITA",
"SUMMARY": "RESUMEN", "SUMMARY": "RESUMEN",
"Awaiting telemetry...": "Esperando telemetría...", "Awaiting telemetry...": "Esperando telemetría...",
"REC": "REC", "REC": "REC",
"Scope edge feather": "Suavizado del borde de la mirilla", "Scope edge feather": "Difuminado del borde de la mirilla",
"Bloom intensity": "Intensidad del bloom", "Bloom intensity": "Intensidad del bloom",
"Sharpen intensity": "Intensidad de la nitidez", "Sharpen intensity": "Intensidad de la nitidez",
"Search location by name or coordinates": "Buscar ubicación por nombre o coordenadas", "Search location by name or coordinates": "Buscar ubicación por nombre o coordenadas",
@@ -391,10 +395,12 @@
"No selected data layers": "No hay capas de datos seleccionadas", "No selected data layers": "No hay capas de datos seleccionadas",
"Cleared {count} data layers": { "Cleared {count} data layers": {
"one": "Se limpió {count} capa de datos", "one": "Se limpió {count} capa de datos",
"many": "Se limpiaron {count} de capas de datos",
"other": "Se limpiaron {count} capas de datos" "other": "Se limpiaron {count} capas de datos"
}, },
"{count} data layers could not be cleared": { "{count} data layers could not be cleared": {
"one": "No se pudo limpiar {count} capa de datos", "one": "No se pudo limpiar {count} capa de datos",
"many": "No se pudieron limpiar {count} de capas de datos",
"other": "No se pudieron limpiar {count} capas de datos" "other": "No se pudieron limpiar {count} capas de datos"
}, },
"Visible map targets": "Objetivos visibles en el mapa", "Visible map targets": "Objetivos visibles en el mapa",
@@ -406,11 +412,11 @@
"CCTV camera": "Cámara CCTV", "CCTV camera": "Cámara CCTV",
"FOCUS": "ENFOCAR", "FOCUS": "ENFOCAR",
"COVERAGE OFF": "COBERTURA DESACTIVADA", "COVERAGE OFF": "COBERTURA DESACTIVADA",
"AUTO HOP OFF": "AUTO HOP DESACTIVADO", "AUTO HOP OFF": "AUTOSALTO DESACTIVADO",
"PROJECTION ON": "PROYECCIÓN ACTIVADA", "PROJECTION ON": "PROYECCIÓN ACTIVADA",
"CALIBRATION": "CALIBRACIÓN", "CALIBRATION": "CALIBRACIÓN",
"ADJUST": "AJUSTAR", "ADJUST": "AJUSTAR",
"Drag the camera in the world: rings rotate, arrows move, handles set range/FOV": "Arrastra la cámara en el mundo: los anillos rotan, las flechas se mueven, los tiradores ajustan alcance/FOV", "Drag the camera in the world: rings rotate, arrows move, handles set range/FOV": "Arrastra la cámara en el mundo: los anillos la giran, las flechas la mueven, los tiradores ajustan alcance/FOV",
"Camera pose — click a value to type": "Pose de la cámara — clic en un valor para escribirlo", "Camera pose — click a value to type": "Pose de la cámara — clic en un valor para escribirlo",
"Heading (compass °) — click to type": "Rumbo (° brújula) — clic para escribir", "Heading (compass °) — click to type": "Rumbo (° brújula) — clic para escribir",
"Pitch (° up/down) — click to type": "Inclinación (° arriba/abajo) — clic para escribir", "Pitch (° up/down) — click to type": "Inclinación (° arriba/abajo) — clic para escribir",
@@ -468,8 +474,8 @@
"FIRMS Active Fires": "Incendios activos FIRMS", "FIRMS Active Fires": "Incendios activos FIRMS",
"just now": "justo ahora", "just now": "justo ahora",
"{count}s ago": "hace {count}s", "{count}s ago": "hace {count}s",
"{count}m ago": "hace {count}m", "{count}m ago": "hace {count} min",
"{count}h ago": "hace {count}h", "{count}h ago": "hace {count} h",
"never": "nunca", "never": "nunca",
"loading...": "cargando...", "loading...": "cargando...",
"UNCERTAIN · {source} · lifecycle state requires reconciliation": "INCIERTO · {source} · el estado del ciclo de vida requiere reconciliación", "UNCERTAIN · {source} · lifecycle state requires reconciliation": "INCIERTO · {source} · el estado del ciclo de vida requiere reconciliación",
@@ -499,7 +505,7 @@
"TUG": "REMOLCADOR", "TUG": "REMOLCADOR",
"PORT TENDER": "AUXILIAR DE PUERTO", "PORT TENDER": "AUXILIAR DE PUERTO",
"ANTI-POLLUTION": "ANTICONTAMINACIÓN", "ANTI-POLLUTION": "ANTICONTAMINACIÓN",
"LAW ENFORCE": "APLICACIÓN DE LA LEY", "LAW ENFORCE": "POLICÍA",
"MEDICAL": "MÉDICO", "MEDICAL": "MÉDICO",
"HIGH-SPEED": "ALTA VELOCIDAD", "HIGH-SPEED": "ALTA VELOCIDAD",
"PASSENGER": "PASAJEROS", "PASSENGER": "PASAJEROS",
@@ -515,7 +521,7 @@
"awaiting first AIS position…": "esperando la primera posición AIS…", "awaiting first AIS position…": "esperando la primera posición AIS…",
"CCTV ON": "CCTV ACTIVADO", "CCTV ON": "CCTV ACTIVADO",
"COVERAGE ON": "COBERTURA ACTIVADA", "COVERAGE ON": "COBERTURA ACTIVADA",
"AUTO HOP ON": "AUTO HOP ACTIVADO", "AUTO HOP ON": "AUTOSALTO ACTIVADO",
"PROJECTION OFF": "PROYECCIÓN DESACTIVADA", "PROJECTION OFF": "PROYECCIÓN DESACTIVADA",
"ADJUST ON": "AJUSTE ACTIVADO", "ADJUST ON": "AJUSTE ACTIVADO",
"{count} CAMERAS STANDING BY · NO CAMERA SELECTED · CLICK A CAMERA TO ACTIVATE": "{count} CÁMARAS EN ESPERA · NINGUNA CÁMARA SELECCIONADA · CLIC EN UNA CÁMARA PARA ACTIVARLA", "{count} CAMERAS STANDING BY · NO CAMERA SELECTED · CLICK A CAMERA TO ACTIVATE": "{count} CÁMARAS EN ESPERA · NINGUNA CÁMARA SELECCIONADA · CLIC EN UNA CÁMARA PARA ACTIVARLA",
@@ -524,21 +530,21 @@
"HDG {value}°": "HDG {value}°", "HDG {value}°": "HDG {value}°",
"HDG {value}° (ESTIMATED)": "HDG {value}° (ESTIMADO)", "HDG {value}° (ESTIMATED)": "HDG {value}° (ESTIMADO)",
"FOV {value}°": "FOV {value}°", "FOV {value}°": "FOV {value}°",
"COVERAGE {value}km²": "COBERTURA {value}km²", "COVERAGE {value}km²": "COBERTURA {value} KM²",
"OVERLAP {count} cams": "SOLAPE {count} cáms", "OVERLAP {count} cams": "SOLAPE {count} cám.",
"ISOLATED VIEW": "VISTA AISLADA", "ISOLATED VIEW": "VISTA AISLADA",
"PROJ MONITOR": "PROY MONITOR", "PROJ MONITOR": "PROY MONITOR",
"PROJ OFF": "PROY DESACT", "PROJ OFF": "PROY DESACT",
"VIEWSHED": "ÁREA VISIBLE", "VIEWSHED": "ÁREA VISIBLE",
"CAL {value}": "CAL {value}", "CAL {value}": "CAL {value}",
"SRC {value}": "SRC {value}", "SRC {value}": "SRC {value}",
"{value} CONTEXT": "{value} CONTEXTO", "{value} CONTEXT": "CONTEXTO {value}",
"News": "Noticias", "News": "Noticias",
"Talk": "Debate", "Talk": "Tertulia",
"Weather / Emergency": "Clima / Emergencias", "Weather / Emergency": "Clima / Emergencias",
"Public Safety": "Seguridad pública", "Public Safety": "Seguridad pública",
"Aviation / Marine": "Aviación / Marítima", "Aviation / Marine": "Aviación / Marina",
"Traffic / Transit": "Tráfico / Tránsito", "Traffic / Transit": "Tráfico / Transporte",
"Music": "Música", "Music": "Música",
"Other": "Otros", "Other": "Otros",
"NO STATION AVAILABLE": "NINGUNA EMISORA DISPONIBLE", "NO STATION AVAILABLE": "NINGUNA EMISORA DISPONIBLE",
@@ -555,7 +561,7 @@
"Connecting directly to broadcaster…": "Conectando directamente con la emisora…", "Connecting directly to broadcaster…": "Conectando directamente con la emisora…",
"Buffering broadcaster stream…": "Almacenando en búfer el flujo de la emisora…", "Buffering broadcaster stream…": "Almacenando en búfer el flujo de la emisora…",
"Playing {station}": "Reproduciendo {station}", "Playing {station}": "Reproduciendo {station}",
"Paused {station}": "En pausa {station}", "Paused {station}": "{station} en pausa",
"Broadcaster stream unavailable": "Flujo de la emisora no disponible", "Broadcaster stream unavailable": "Flujo de la emisora no disponible",
" · degraded directory": " · directorio degradado", " · degraded directory": " · directorio degradado",
" · stale directory": " · directorio desactualizado", " · stale directory": " · directorio desactualizado",
@@ -640,19 +646,19 @@
"Showing the full Starlink shell — click for the core catalog only": "Mostrando la capa completa de Starlink — clic para ver solo el catálogo principal", "Showing the full Starlink shell — click for the core catalog only": "Mostrando la capa completa de Starlink — clic para ver solo el catálogo principal",
"STATION": "ESTACIÓN", "STATION": "ESTACIÓN",
"Crewed stations and their visiting vehicles": "Estaciones tripuladas y sus vehículos de visita", "Crewed stations and their visiting vehicles": "Estaciones tripuladas y sus vehículos de visita",
"NAV": "NAVEGACIÓN", "NAV": "NAV",
"GNSS navigation — GPS, GLONASS, Galileo": "Navegación GNSS — GPS, GLONASS, Galileo", "GNSS navigation — GPS, GLONASS, Galileo": "Navegación GNSS — GPS, GLONASS, Galileo",
"GEO": "GEO", "GEO": "GEO",
"Geostationary belt — comms and weather, fixed over the equator": "Cinturón geoestacionario — comunicaciones y meteorología, fijos sobre el ecuador", "Geostationary belt — comms and weather, fixed over the equator": "Cinturón geoestacionario — comunicaciones y meteorología, fijos sobre el ecuador",
"VISUAL": "VISUAL", "VISUAL": "VISUAL",
"Brightest naked-eye objects — CelesTrak visual group": "Objetos más brillantes a simple vista — grupo visual de CelesTrak", "Brightest naked-eye objects — CelesTrak visual group": "Objetos más brillantes a simple vista — grupo visual de CelesTrak",
"COMMS": "COMUNICACIONES", "COMMS": "TELECOM",
"Broadband constellation shell — shown only in DENSE mode": "Capa de constelación de banda ancha — visible solo en modo DENSO", "Broadband constellation shell — shown only in DENSE mode": "Capa de constelación de banda ancha — visible solo en modo DENSO",
"refreshing...": "actualizando...", "refreshing...": "actualizando...",
"KEY REQUIRED": "CLAVE REQUERIDA", "KEY REQUIRED": "CLAVE REQUERIDA",
"STALE · cached {age}": "DESACTUALIZADO · en caché hace {age}", "STALE · cached {age}": "DESACTUALIZADO · en caché hace {age}",
"LIVE · updated {age}": "EN VIVO · actualizado hace {age}", "LIVE · updated {age}": "EN VIVO · actualizado {age}",
"<1m ago": "hace <1m", "<1m ago": "hace <1 min",
"FIRE · {frp} MW": "INCENDIO · {frp} MW", "FIRE · {frp} MW": "INCENDIO · {frp} MW",
"▲ {frp} MW": "▲ {frp} MW", "▲ {frp} MW": "▲ {frp} MW",
"FIRE": "INCENDIO", "FIRE": "INCENDIO",
@@ -700,7 +706,7 @@
"Military flights": "Vuelos militares", "Military flights": "Vuelos militares",
"AIS vessels": "Buques AIS", "AIS vessels": "Buques AIS",
"Mapped installations": "Instalaciones mapeadas", "Mapped installations": "Instalaciones mapeadas",
"CURRENT VIEWPORT ONLY": "SOLO LA VENTANA VISIBLE ACTUAL", "CURRENT VIEWPORT ONLY": "SOLO LA VISTA ACTUAL",
"BRG {value}°": "BRG {value}°", "BRG {value}°": "BRG {value}°",
"CRS {value}°": "CRS {value}°", "CRS {value}°": "CRS {value}°",
"feed unavailable": "fuente no disponible", "feed unavailable": "fuente no disponible",
@@ -719,7 +725,7 @@
"SNOW SHOWERS": "CHUBASCOS DE NIEVE", "SNOW SHOWERS": "CHUBASCOS DE NIEVE",
"THUNDERSTORM": "TORMENTA", "THUNDERSTORM": "TORMENTA",
"MIXED CONDITIONS": "CONDICIONES MIXTAS", "MIXED CONDITIONS": "CONDICIONES MIXTAS",
"TAB PREVIEWS · ENTER / SPACE SELECTS": "TAB VISTAS PREVIAS · INTRO / ESPACIO SELECCIONA", "TAB PREVIEWS · ENTER / SPACE SELECTS": "TAB VISTA PREVIA · ENTER / SPACE SELECCIONA",
"awaiting usable AIS positions…": "esperando posiciones AIS utilizables…", "awaiting usable AIS positions…": "esperando posiciones AIS utilizables…",
"awaiting first AIS message…": "esperando el primer mensaje AIS…", "awaiting first AIS message…": "esperando el primer mensaje AIS…",
"EST. DOWNRANGE": "DIST. ESTIMADA", "EST. DOWNRANGE": "DIST. ESTIMADA",
@@ -733,12 +739,12 @@
"SAVE KEYS": "GUARDAR CLAVES", "SAVE KEYS": "GUARDAR CLAVES",
"Saving…": "Guardando…", "Saving…": "Guardando…",
"It feels like a forbidden cockpit—then you realize the sources are public and the data is real.": "Parece una cabina prohibida—hasta que descubres que las fuentes son públicas y los datos son reales.", "It feels like a forbidden cockpit—then you realize the sources are public and the data is real.": "Parece una cabina prohibida—hasta que descubres que las fuentes son públicas y los datos son reales.",
"Aircraft, vessels and nearby intelligence": "Aviones, barcos e inteligencia cercana", "Aircraft, vessels and nearby intelligence": "Aeronaves, buques e inteligencia cercana",
"Launches, spacecraft and orbital context": "Lanzamientos, naves y contexto orbital", "Launches, spacecraft and orbital context": "Lanzamientos, naves y contexto orbital",
"EXPLORE MANUALLY": "EXPLORAR MANUALMENTE", "EXPLORE MANUALLY": "EXPLORAR MANUALMENTE",
"Begin with a clean globe": "Empieza con un globo limpio", "Begin with a clean globe": "Empieza con un globo limpio",
"ESC to dismiss": "ESC para cerrar", "ESC to dismiss": "ESC para cerrar",
"Tip: the GEV MIC button in the dock lets you talk to the map.": "Consejo: el botón MIC de GEV en el dock te permite hablar con el mapa.", "Tip: the GEV MIC button in the dock lets you talk to the map.": "Consejo: el botón GEV MIC del dock te permite hablar con el mapa.",
"Close key setup": "Cerrar la configuración de claves", "Close key setup": "Cerrar la configuración de claves",
"The globe already flies keyless. Every key below switches on another real feed — paste one and it's saved into this app's local configuration, then the server restarts itself. Server-side keys stay on this machine; Google Maps and Cesium ion run in the browser and must be provider-restricted. Keys you configured elsewhere are shown but never touched.": "El globo ya vuela sin claves. Cada clave de abajo activa otra fuente real — pega una y queda guardada en la configuración local de esta app, y luego el servidor se reinicia solo. Las claves del servidor se quedan en esta máquina; Google Maps y Cesium ion funcionan en el navegador y sus claves deben estar restringidas por el proveedor. Las claves que configuraste en otro lugar se muestran, pero nunca se modifican.", "The globe already flies keyless. Every key below switches on another real feed — paste one and it's saved into this app's local configuration, then the server restarts itself. Server-side keys stay on this machine; Google Maps and Cesium ion run in the browser and must be provider-restricted. Keys you configured elsewhere are shown but never touched.": "El globo ya vuela sin claves. Cada clave de abajo activa otra fuente real — pega una y queda guardada en la configuración local de esta app, y luego el servidor se reinicia solo. Las claves del servidor se quedan en esta máquina; Google Maps y Cesium ion funcionan en el navegador y sus claves deben estar restringidas por el proveedor. Las claves que configuraste en otro lugar se muestran, pero nunca se modifican.",
"ESC to close": "ESC para cerrar", "ESC to close": "ESC para cerrar",
@@ -759,12 +765,13 @@
"Working…": "Trabajando…", "Working…": "Trabajando…",
"Could not open that mission{detail}. Retry or explore manually.": "No se pudo abrir esa misión{detail}. Reintenta o explora manualmente.", "Could not open that mission{detail}. Retry or explore manually.": "No se pudo abrir esa misión{detail}. Reintenta o explora manualmente.",
"This browser is blocking storage, so that could not be saved.": "Este navegador bloquea el almacenamiento, así que no se pudo guardar.", "This browser is blocking storage, so that could not be saved.": "Este navegador bloquea el almacenamiento, así que no se pudo guardar.",
"Live earthquakes and active fires, from USGS and NASA": "Terremotos en vivo y fuegos activos, de USGS y NASA", "Live earthquakes and active fires, from USGS and NASA": "Terremotos en vivo e incendios activos, de USGS y NASA",
"ENVIRONMENTAL": "MEDIO AMBIENTE", "ENVIRONMENTAL": "MEDIO AMBIENTE",
"EARTH WATCH": "VIGILANCIA TERRESTRE", "EARTH WATCH": "VIGILANCIA TERRESTRE",
"ACTIVE EVENTS": "EVENTOS ACTIVOS", "ACTIVE EVENTS": "EVENTOS ACTIVOS",
"POWER UP · {count} KEYS WAITING": { "POWER UP · {count} KEYS WAITING": {
"one": "ENCENDER · {count} CLAVE EN ESPERA", "one": "ENCENDER · {count} CLAVE EN ESPERA",
"many": "ENCENDER · {count} DE CLAVES EN ESPERA",
"other": "ENCENDER · {count} CLAVES EN ESPERA" "other": "ENCENDER · {count} CLAVES EN ESPERA"
}, },
"POWERED UP": "ENCENDIDO", "POWERED UP": "ENCENDIDO",
@@ -794,13 +801,13 @@
"VOICE UNAVAILABLE": "VOZ NO DISPONIBLE", "VOICE UNAVAILABLE": "VOZ NO DISPONIBLE",
"WebRTC microphone support unavailable": "Compatibilidad con micrófono WebRTC no disponible", "WebRTC microphone support unavailable": "Compatibilidad con micrófono WebRTC no disponible",
"Requesting microphone": "Solicitando micrófono", "Requesting microphone": "Solicitando micrófono",
"Hold Space to talk": "Mantén Espacio para hablar", "Hold Space to talk": "Mantén pulsado Space para hablar",
"Release Space to send": "Suelta la barra espaciadora para enviar", "Release Space to send": "Suelta Space para enviar",
"Ask or command": "Pregunta o ordena", "Ask or command": "Pregunta o ordena",
"Voice off": "Voz desactivada", "Voice off": "Voz desactivada",
"Running command": "Ejecutando comando", "Running command": "Ejecutando comando",
"Radio did not start": "La radio no se inició", "Radio did not start": "La radio no se inició",
"Hold Space to speak · tap Space to activate focused controls": "Mantén presionada la barra espaciadora para hablar · púlsala brevemente para activar los controles enfocados", "Hold Space to speak · tap Space to activate focused controls": "Mantén pulsado Space para hablar · pulsa Space brevemente para activar el control enfocado",
"Voice session could not be started.": "No se pudo iniciar la sesión de voz.", "Voice session could not be started.": "No se pudo iniciar la sesión de voz.",
"VOICE SYSTEM ERROR": "ERROR DEL SISTEMA DE VOZ", "VOICE SYSTEM ERROR": "ERROR DEL SISTEMA DE VOZ",
"DISMISS": "CERRAR", "DISMISS": "CERRAR",
@@ -810,7 +817,7 @@
"{tier} applies next session": "{tier} se aplica en la próxima sesión", "{tier} applies next session": "{tier} se aplica en la próxima sesión",
"Voice model tier — applies next session": "Nivel del modelo de voz — se aplica en la próxima sesión", "Voice model tier — applies next session": "Nivel del modelo de voz — se aplica en la próxima sesión",
"Estimated session cost": "Costo estimado de la sesión", "Estimated session cost": "Costo estimado de la sesión",
"Voice control — activate to toggle voice; hold Space to speak": "Control de voz — actívalo para conectar o cortar la voz; mantén presionada la barra espaciadora para hablar", "Voice control — activate to toggle voice; hold Space to speak": "Control de voz — actívalo para conectar o cortar la voz; mantén pulsado Space para hablar",
"Cannot capture shot: camera not ready": "No se puede capturar el plano: la cámara no está lista", "Cannot capture shot: camera not ready": "No se puede capturar el plano: la cámara no está lista",
"Shot {n}": "Plano {n}", "Shot {n}": "Plano {n}",
"Captured: {scene} / {shot}": "Capturado: {scene} / {shot}", "Captured: {scene} / {shot}": "Capturado: {scene} / {shot}",
@@ -829,7 +836,7 @@
"Needs {envVars} — add it in Provider Settings": "Necesita {envVars} — añádela en Ajustes de proveedores", "Needs {envVars} — add it in Provider Settings": "Necesita {envVars} — añádela en Ajustes de proveedores",
"The photorealistic 3D planet + place search": "El planeta 3D fotorrealista + búsqueda de lugares", "The photorealistic 3D planet + place search": "El planeta 3D fotorrealista + búsqueda de lugares",
"Places context + Street View fallback; optional separate key": "Contexto de Places + respaldo de Street View; clave separada opcional", "Places context + Street View fallback; optional separate key": "Contexto de Places + respaldo de Street View; clave separada opcional",
"Live ships, worldwide": "Barcos en vivo, en todo el mundo", "Live ships, worldwide": "Buques en vivo, en todo el mundo",
"Live active-fire detections": "Detecciones de incendios activos en vivo", "Live active-fire detections": "Detecciones de incendios activos en vivo",
"Real live traffic (keyless runs a simulation)": "Tráfico real en vivo (sin clave usa una simulación)", "Real live traffic (keyless runs a simulation)": "Tráfico real en vivo (sin clave usa una simulación)",
"Bing imagery map stacks + world terrain": "Conjuntos de mapas Bing imagery + terreno mundial", "Bing imagery map stacks + world terrain": "Conjuntos de mapas Bing imagery + terreno mundial",
@@ -838,6 +845,19 @@
"Scene action failed": "La acción de escena falló", "Scene action failed": "La acción de escena falló",
"Project exported": "Proyecto exportado", "Project exported": "Proyecto exportado",
"Next session: {pendingId} — this session stays on {modelId}": "Sesión siguiente: {pendingId} — esta sesión sigue en {modelId}", "Next session: {pendingId} — this session stays on {modelId}": "Sesión siguiente: {pendingId} — esta sesión sigue en {modelId}",
"Voice model: {pendingId} — click to switch to {target}; applies next session": "Modelo de voz: {pendingId} — toca para cambiar a {target}; se aplica en la próxima sesión", "Voice model: {pendingId} — click to switch to {target}; applies next session": "Modelo de voz: {pendingId} — haz clic para cambiar a {target}; se aplica en la próxima sesión",
"Estimated session cost on {modelId} — {responses} response(s). Warns at {warn}, ends the session at {cap}.": "Coste de sesión estimado en {modelId} — {responses} respuesta(s). Avisa a {warn} y cierra la sesión a {cap}." "Estimated session cost on {modelId} — {responses} response(s). Warns at {warn}, ends the session at {cap}.": "Costo de sesión estimado en {modelId} — {responses} respuesta(s). Avisa a {warn} y cierra la sesión a {cap}.",
"Street-level imagery and coverage in the Street Level layer. Free: register an app in the Mapillary developer dashboard and paste its Client Token": "Imágenes y cobertura a nivel de calle en la capa Street Level. Gratis: registra una app en el panel de desarrolladores de Mapillary y pega su Client Token",
"Voice control — API key or ChatGPT OAuth": "Control de voz — clave de API u OAuth de ChatGPT",
"WITHIN {km} KM": "A MENOS DE {km} KM",
"Syncing flow · Roads: {source}": "Sincronizando flujo · Vías: {source}",
"LIVE · Roads: {source} · Roads without flow hidden": "EN VIVO · Vías: {source} · Vías sin flujo ocultas",
"LIVE · Roads: {source} · No flow roads in view": "EN VIVO · Vías: {source} · Sin vías con flujo a la vista",
"LIVE · Roads: {source} · Flow {percent}%": "EN VIVO · Vías: {source} · Flujo {percent}%",
"SIMULATED · Roads: {source} · Flow {percent}%": "SIMULADO · Vías: {source} · Flujo {percent}%",
"Syncing flow · Roads: OpenStreetMap · Flow: TomTom · Unmatched: simulated": "Sincronizando flujo · Vías: OpenStreetMap · Flujo: TomTom · Sin coincidencia: simulado",
"LIVE · Roads: OpenStreetMap · Flow: TomTom · {percent}% cov · Unmatched: simulated": "EN VIVO · Vías: OpenStreetMap · Flujo: TomTom · {percent}% cob. · Sin coincidencia: simulado",
"LIVE · Roads: OpenStreetMap · Flow: TomTom · {percent}% cov": "EN VIVO · Vías: OpenStreetMap · Flujo: TomTom · {percent}% cob.",
"SIMULATED · Roads: OpenStreetMap · Flow: TomTom (no matches)": "SIMULADO · Vías: OpenStreetMap · Flujo: TomTom (sin coincidencias)",
"Data source unavailable": "Fuente de datos no disponible"
} }