fix(i18n): wording, dates and directions from the cross-model review

Two other models reviewed the ru and es review PDFs. What held up:

- Directions: Russian reads "держитесь левее" at a fork and "займите
  левую полосу" for a lane, Spanish "toma el carril izquierdo". Forks and
  lanes get their own direction words; English is unchanged.
- Weather timestamps read "13.10 19:04 UTC" / "13/10 19:04 UTC" instead
  of "10-13", which read as a range. English keeps "10-13".
- Cockpit coordinates write the hemisphere out in Russian ("30,312° с.
  ш."): a lone «С» after a degree sign read as Celsius.
- A layer whose source joins several providers shows each name in the UI
  language ("Mapillary · Google Просмотр улиц").
- Vessel speed uses the locale's decimal separator.
- Layer names no longer hyphenate into two-letter pieces ("es-paciales").
- Catalog: wrong meanings (cyclone centre, STREAMING, credited source,
  "DE OÍDAS"), calques ("Пацифика", "Активная погода", "Прочитать вид",
  "referrer", worker), Russian "щёлкните по …", shorter Spanish labels
  that were cut (voice status, PREAJUSTES, search placeholder) and one
  term per concept.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
German KhokhlovandClaude Opus 5.5 committed 2026-10-14 17:31:42 +04:00
1 parent 005b4dc9dc
commit eed05721f2
13 files changed
+278 -134

No files matched your search

+26
View File
@@ -164,6 +164,32 @@ export function formatDate(value, options) {
return cachedFormatter('date', Intl.DateTimeFormat, options).format(value);
}
const UTC_DAY_MONTH = Object.freeze({
day: '2-digit',
month: '2-digit',
timeZone: 'UTC',
});
/**
* The UTC day and month of a time, for "MM-DD HH:MM UTC" readouts: "10-13" in
* English (as before), "13.10" in Russian, "13/10" in Spanish, never read as a
* range. Takes an ISO string (its date part is used as written) or a time.
* @param {string|number|Date} value
* @returns {string} '' when the value is not a time.
*/
export function formatUtcDayMonth(value) {
const written =
typeof value === 'string' ? /^(\d{4})-(\d{2})-(\d{2})/.exec(value) : null;
const time = written
? Date.UTC(Number(written[1]), Number(written[2]) - 1, Number(written[3]))
: new Date(value).getTime();
if (!Number.isFinite(time)) return '';
if (currentLocale === 'en') return new Date(time).toISOString().slice(5, 10);
return cachedFormatter('date', Intl.DateTimeFormat, UTC_DAY_MONTH).format(
time,
);
}
/**
* Locale-aware relative time (Intl.RelativeTimeFormat), e.g.
* formatRelativeTime(-5, 'minute') → '5 minutes ago' / '5 минут назад'.
+60 -42
View File
@@ -47,7 +47,7 @@
"Return UI controls": "Volver a mostrar los controles de la interfaz",
"EXIT CLEAN VIEW": "SALIR DE VISTA LIMPIA",
"Expand Visual Presets": "Expandir Preajustes visuales",
"VISUAL PRESETS": "PREAJUSTES VISUALES",
"VISUAL PRESETS": "PREAJUSTES",
"Pin visual presets": "Fijar Preajustes visuales",
"Keep visual presets open": "Mantener abiertos los Preajustes visuales",
"Show the globe without a visual filter.": "Muestra el globo sin filtro visual.",
@@ -83,7 +83,7 @@
"Detection label allocation": "Asignación de etiquetas de detección",
"Elastic": "Elástica",
"Weighted": "Ponderada",
"Fade": "Desvanecido",
"Fade": "Desvanecimiento",
"Detection fade distance": "Distancia de desvanecimiento de detección",
"World-overlay fade distance outside the keyhole as a percentage of its radius": "Distancia de desvanecimiento de la superposición del mundo fuera del ojo de cerradura, como porcentaje de su radio",
"Outside": "Exterior",
@@ -112,8 +112,8 @@
"Keep location tray open": "Mantener abierta la bandeja de ubicación",
"📍 Location: --": "📍 Ubicación: --",
"Landmark: --": "Punto de interés: --",
"Search any location": "Buscar cualquier ubicación",
"Search any location...": "Buscar cualquier ubicación...",
"Search any location": "Buscar un lugar",
"Search any location...": "Buscar un lugar…",
"LEVEL": "NIVEL",
"Estimated destination direction": "Dirección estimada del destino",
"DEST ---°": "DEST ---°",
@@ -412,7 +412,7 @@
"CCTV camera": "Cámara CCTV",
"FOCUS": "ENFOCAR",
"COVERAGE OFF": "COBERTURA DESACTIVADA",
"AUTO HOP OFF": "SALTO AUTOMÁTICO: NO",
"AUTO HOP OFF": "SALTO AUTO: NO",
"PROJECTION ON": "PROYECCIÓN ACTIVADA",
"CALIBRATION": "CALIBRACIÓN",
"ADJUST": "AJUSTAR",
@@ -473,7 +473,7 @@
"Submarine Cables": "Cables submarinos",
"FIRMS Active Fires": "Incendios activos FIRMS",
"just now": "justo ahora",
"{count}s ago": "hace {count}s",
"{count}s ago": "hace {count} s",
"{count}m ago": "hace {count} min",
"{count}h ago": "hace {count} h",
"never": "sin actualizar",
@@ -521,7 +521,7 @@
"awaiting first AIS position…": "esperando la primera posición AIS…",
"CCTV ON": "CCTV ACTIVADO",
"COVERAGE ON": "COBERTURA ACTIVADA",
"AUTO HOP ON": "SALTO AUTOMÁTICO: SÍ",
"AUTO HOP ON": "SALTO AUTO: SÍ",
"PROJECTION OFF": "PROYECCIÓN DESACTIVADA",
"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",
@@ -540,7 +540,7 @@
"SRC {value}": "SRC {value}",
"{value} CONTEXT": "CONTEXTO {value}",
"News": "Noticias",
"Talk": "Tertulia",
"Talk": "Radio hablada",
"Weather / Emergency": "Clima / Emergencias",
"Public Safety": "Seguridad pública",
"Aviation / Marine": "Aviación / Marina",
@@ -698,7 +698,7 @@
"SELECT A FLIGHT, VESSEL, OR MAPPED INSTALLATION": "SELECCIONA UN VUELO, BUQUE U INSTALACIÓN MAPEADA",
"ENABLE TO LOAD OBSERVED / MAPPED PROXIMITY": "ACTIVA PARA CARGAR PROXIMIDAD OBSERVADA / MAPEADA",
"Global Context navigation": "Navegación del Contexto global",
"PREVIOUS": "ANTERIOR",
"PREVIOUS": "ANT.",
"Open-source mapped/observed context. Missing broadcasts, unloaded map areas, or unmapped sites are not evidence of absence.": "Contexto mapeado/observado de fuentes abiertas. Las transmisiones ausentes, las zonas del mapa sin cargar o los sitios sin mapear no son evidencia de ausencia.",
"Unavailable": "No disponible",
"Focus {label}": "Enfocar {label}",
@@ -815,7 +815,7 @@
"{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",
"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 pulsado Space para hablar",
"Voice control — activate to toggle voice; hold Space to speak": "Control de voz — púlsalo para activar o desactivar 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",
"Shot {n}": "Plano {n}",
"Captured: {scene} / {shot}": "Capturado: {scene} / {shot}",
@@ -981,12 +981,12 @@
"Could not place the shape: {error}": "No se pudo colocar la forma: {error}",
"{owner} is using the pointer — close it first.": "{owner} está usando el puntero — ciérralo primero.",
"{label} · Detailed outline unavailable": "{label} · Contorno detallado no disponible",
"Witness source": "Fuente testigo",
"Witness source": "Testimonio de testigo",
"{provider} · EMBEDDED SOURCE": "{provider} · FUENTE INSERTADA",
"OPEN ORIGINAL ↗": "ABRIR ORIGINAL ↗",
"{provider} media: {source}": "Contenido de {provider}: {source}",
"{provider} · PROVIDER CONTROLS": "{provider} · CONTROLES NATIVOS",
"YOUTUBE {state} · OPEN ORIGINAL": "YOUTUBE {state} · ABRE EL ORIGINAL",
"YOUTUBE {state} · OPEN ORIGINAL": "YOUTUBE {state} · ABRIR ORIGINAL",
"Facebook player API did not initialize.": "La API del reproductor de Facebook no se inicializó.",
"Facebook player API could not load.": "No se pudo cargar la API del reproductor de Facebook.",
"Facebook player API timed out.": "La API del reproductor de Facebook agotó el tiempo de espera.",
@@ -1006,7 +1006,7 @@
"Facebook embed unavailable": "Inserción de Facebook no disponible",
"AUTOPLAY BLOCKED · USE PROVIDER CONTROLS": "REPRODUCCIÓN AUTOMÁTICA BLOQUEADA · USA LOS CONTROLES DEL PROVEEDOR",
"Embedded {provider} media for {source}": "Contenido de {provider} insertado para {source}",
"witness source": "fuente testigo",
"witness source": "testimonio de testigo",
"Rasuwagadhi witness": "Testigo de Rasuwagadhi",
"Open original source for {source}; capture time unverified": "Abrir la fuente original de {source}; hora de captura sin verificar",
"Historical reference and post-event image divider": "Divisor entre la imagen de referencia histórica y la posterior al evento",
@@ -1100,8 +1100,8 @@
"NEPAL · 26 AUG 2026": "NEPAL · 26 AGO 2026",
"USGS INITIAL REPORT": "INFORME INICIAL DEL USGS",
"26 AUG 2026 · 08:37 NPT": "26 AGO 2026 · 08:37 NPT",
"28.2710° N · 85.5150° E": "28.2710° N · 85.5150° E",
"INITIAL M4.4 · RECLASSIFIED M5.2 LANDSLIDE": "INICIAL M4.4 · RECLASIFICADO COMO DESLIZAMIENTO M5.2",
"28.2710° N · 85.5150° E": "28,2710° N · 85,5150° E",
"INITIAL M4.4 · RECLASSIFIED M5.2 LANDSLIDE": "INICIAL M4,4 · RECLASIFICADO COMO DESLIZAMIENTO M5,2",
"USGS EVENT us7000tbwb · OPEN SOURCE": "EVENTO USGS us7000tbwb · ABRIR FUENTE",
"flight": "vuelo",
"military flight": "vuelo militar",
@@ -1177,7 +1177,7 @@
"Official advisory ↗": "Aviso oficial ↗",
"Active NHC and CPHC cyclone advisories": "Avisos de ciclones activos del NHC y el CPHC",
"Wind unavailable": "Viento no disponible",
"Advisory center / forecast track": "Centro del aviso / trayectoria pronosticada",
"Advisory center / forecast track": "Centro del ciclón según el aviso / trayectoria pronosticada",
"Center-track uncertainty cone": "Cono de incertidumbre de la trayectoria del centro",
"Select a storm on the map, or choose a storm in the list to select it and move the camera. Click empty map space to clear the selection. NOAA NHC/CPHC advisory context. The cone describes forecast center-track uncertainty, not storm size or the full hazard area. Forecast point labels are source lead hours, not times computed from advisory issuance. Geometry follows the surface; height is not weather altitude. Consult the official advisory.": "Selecciona un ciclón en el mapa, o elige uno en la lista para seleccionarlo y mover la cámara. Haz clic en un espacio vacío del mapa para borrar la selección. Contexto de avisos NOAA NHC/CPHC. El cono describe la incertidumbre de la trayectoria pronosticada del centro, no el tamaño del ciclón ni toda el área de peligro. Las etiquetas de los puntos de pronóstico son horas de anticipación de la fuente, no horas calculadas a partir de la emisión del aviso. La geometría sigue la superficie; la altura no es altitud meteorológica. Consulta el aviso oficial.",
"Directions": "Indicaciones",
@@ -1196,7 +1196,7 @@
"Fly the camera along the route": "Volar con la cámara a lo largo de la ruta",
"Place A and B first": "Coloca primero A y B",
"Remove the route and both markers": "Eliminar la ruta y ambos marcadores",
"press Escape twice to leave Draw": "pulsa Escape dos veces para salir de Dibujo",
"press Escape twice to leave Draw": "pulsa Esc dos veces para salir de Dibujo",
"{name} is active — turn {name} off, then set {endpoint}": "{name} está activo — desactiva {name} y luego fija {endpoint}",
"{name} is active — {leave}, then set {endpoint}": "{name} está activo — {leave} y luego fija {endpoint}",
"Only the first {count} turns of this route are shown": "Solo se muestran los primeros {count} giros de esta ruta",
@@ -1266,7 +1266,7 @@
"60°S–60°N · typically 2–3 h delayed": "60°S–60°N · normalmente con 2–3 h de retraso",
"North America · infrared imagery": "Norteamérica · imágenes infrarrojas",
"Reduced motion · history playback unavailable": "Movimiento reducido · reproducción del historial no disponible",
"Reduced motion · manual history available": "Movimiento reducido · historial manual disponible",
"Reduced motion · manual history available": "Movimiento reducido · puedes recorrer el historial a mano",
"Rain radar · US": "Radar de lluvia · EE. UU.",
"Lightning density · 15 min": "Densidad de rayos · 15 min",
"Satellite clouds": "Nubes por satélite",
@@ -1353,7 +1353,7 @@
"Seeked: {scene} / {shot}": "Saltado a: {scene} / {shot}",
"Scene transition limit reached — load a shot to reset": "Límite de transiciones de escena alcanzado — carga un plano para restablecer",
"Export failed: {error}": "La exportación falló: {error}",
"Imported {file}": "Importado {file}",
"Imported {file}": "Importado: {file}",
"Import failed: {error}": "La importación falló: {error}",
"Import failed (could not read JSON file)": "La importación falló (no se pudo leer el archivo JSON)",
"Layers refused: {layers}": "Capas rechazadas: {layers}",
@@ -1433,7 +1433,7 @@
"No FM signal found": "No se encontró ninguna señal FM",
"Seek stopped": "Búsqueda detenida",
"Browser location is unavailable": "La ubicación del navegador no está disponible",
"Receiver location was not granted": "No se concedió la ubicación del receptor",
"Receiver location was not granted": "No se concedió permiso para la ubicación del receptor",
"RTL-SDR disconnected": "RTL-SDR desconectado",
"No RTL-SDR device selected": "No hay ningún dispositivo RTL-SDR seleccionado",
"WebUSB requires desktop Chrome or Edge on localhost/HTTPS": "WebUSB requiere Chrome o Edge de escritorio en localhost/HTTPS",
@@ -1443,7 +1443,7 @@
"Receiving broadcast FM": "Recibiendo FM de radiodifusión",
"Connect an RTL-SDR to begin.": "Conecta un RTL-SDR para empezar.",
"WebUSB is unavailable in this browser": "WebUSB no está disponible en este navegador",
"SDR decoder worker failed": "El worker del decodificador SDR falló",
"SDR decoder worker failed": "Falló el proceso del decodificador SDR",
"WebUSB requires desktop Chrome or Edge": "WebUSB requiere Chrome o Edge de escritorio",
"Waiting for an RTL-SDR device…": "Esperando un dispositivo RTL-SDR…",
"Browser audio is suspended; press Connect again to resume it": "El audio del navegador está suspendido; pulsa Conectar de nuevo para reanudarlo",
@@ -1468,9 +1468,9 @@
"Weather": "Clima",
"LOCATED": "UBICADO",
"LOCATE": "UBICAR",
"IDLE": "INACTIVO",
"IDLE": "EN ESPERA",
"TUNING": "SINTONIZANDO",
"STREAMING": "TRANSMITIENDO",
"STREAMING": "RECIBIENDO",
"UNSUPPORTED": "NO COMPATIBLE",
"waiting for IQ": "esperando IQ",
"{count} messages": {
@@ -1488,9 +1488,9 @@
"audio signal --": "señal de audio --",
"audio {state}": "audio {state}",
"{count} HEARD": {
"one": "{count} OÍDA",
"many": "{count} DE OÍDAS",
"other": "{count} OÍDAS"
"one": "CAPTADAS: {count}",
"many": "CAPTADAS: {count}",
"other": "CAPTADAS: {count}"
},
"DISCONNECT": "DESCONECTAR",
"CONNECT": "CONECTAR",
@@ -1513,7 +1513,7 @@
"Imagery days, newest first · arrows move, S or A and B pin": "Días de imágenes, el más reciente primero · las flechas mueven, S o A y B fijan",
"On the map": "En el mapa",
"Mode": "Modo",
"Imagery on Esri · Google 3D returns when cleared": "Imágenes sobre Esri · Google 3D vuelve al borrarlas",
"Imagery on Esri · Google 3D returns when cleared": "Imágenes sobre Esri · BORRAR devuelve Google 3D",
"Imagery opacity": "Opacidad de las imágenes",
"SWAP": "INVERTIR",
"VS BASEMAP": "VS MAPA BASE",
@@ -1644,7 +1644,7 @@
"POSITIONED": "POSICIONADAS",
"SDR VOL": "VOL. SDR",
"LOCAL RTL-SDR": "RTL-SDR LOCAL",
"Cyber sonar contact scanner": "Escáner sonar de contactos Ciber",
"Cyber sonar contact scanner": "Escáner de contactos del sonar Ciber",
"Sonar ring count": "Número de anillos del sonar",
"Sonar ring range": "Alcance de los anillos del sonar",
"Sonar intensity": "Intensidad del sonar",
@@ -1669,7 +1669,7 @@
"{detail} · Does not follow history": "{detail} · No sigue el historial",
"Forecast · valid {valid}": "Pronóstico · válido {valid}",
"{time} · {minutes} min ago": "{time} · hace {minutes} min",
"Active weather": "Clima activo",
"Active weather": "Capas meteorológicas activas",
"MINI": "MINI",
"STD": "EST.",
"standard": "estándar",
@@ -1679,7 +1679,7 @@
"USD cost and the API spend cap are unavailable for this auth mode.": "El costo en USD y el límite de gasto de la API no están disponibles con este modo de autenticación.",
"Usage is incomplete because a response was still in flight when the session ended.": "El uso está incompleto porque una respuesta seguía en curso cuando terminó la sesión.",
"Toggle voice control": "Alternar el control de voz",
"Activate to toggle voice": "Activa para conectar o cortar la voz",
"Activate to toggle voice": "Pulsa para activar o desactivar la voz",
"Voice active": "Voz activa",
"Voice could not be started.": "No se pudo iniciar la voz.",
"degraded": "degradado",
@@ -1749,7 +1749,7 @@
"Mark {targets}": "Marcar {targets}",
"Fly to {place}": "Volar a {place}",
"Nearest aircraft to {place}": "Aeronaves más cercanas a {place}",
"Read the view": "Leer la vista",
"Read the view": "Consultar la vista",
"Check view state": "Comprobar el estado de la vista",
"Frame {target}": "Encuadrar {target}",
"Finding places": "Buscando lugares",
@@ -1759,7 +1759,7 @@
"Turning on layer": "Activando capa",
"Loading aircraft": "Cargando aeronaves",
"Picking nearest": "Eligiendo la más cercana",
"Working": "Trabajando",
"Working": "Procesando",
"{value} feet": "{value} pies",
"nominal": "nominal",
"Source: {label}": "Fuente: {label}",
@@ -1884,11 +1884,11 @@
"At the roundabout, continue onto {road}": "En la rotonda, continúa por {road}",
"Exit the roundabout": "Sal de la rotonda",
"Exit the roundabout onto {road}": "Sal de la rotonda hacia {road}",
"Use the {direction} lane": "Usa el carril {direction}",
"Use the {direction} lane onto {road}": "Usa el carril {direction} hacia {road}",
"Use the {direction} lane": "Toma el carril {direction}",
"Use the {direction} lane onto {road}": "Toma el carril {direction} hacia {road}",
"voice|OFF": "APAG.",
"voice|CONNECTING": "CONECT.",
"voice|LISTENING": "ESCUCHO",
"voice|CONNECTING": "CONEX…",
"voice|LISTENING": "OYENDO",
"voice|EXECUTING": "ACCIÓN",
"voice|ERROR": "ERROR",
"MIC": "MIC",
@@ -1897,7 +1897,7 @@
"Outline traced": "Contorno trazado",
"Outline unavailable": "Contorno no disponible",
"in progress": "en curso",
"done": "listo",
"done": "hecho",
"failed": "falló",
"cancelled": "cancelado",
"view band|STREET": "CALLE",
@@ -1967,7 +1967,7 @@
"Flood footage": "Imágenes de la inundación",
"Compilation and casualty claims": "Recopilación y afirmaciones sobre víctimas",
"SOURCE GEOCONFIRMED · WORLD-PINNED": "FUENTE GEOCONFIRMADA · FIJADA EN EL MAPA",
"SOURCE CREDITED · LOCATION UNRESOLVED": "FUENTE ACREDITADA · UBICACIÓN SIN RESOLVER",
"SOURCE CREDITED · LOCATION UNRESOLVED": "AUTORÍA INDICADA · UBICACIÓN SIN DETERMINAR",
"REFERENCE ONLY · CLAIMS UNVERIFIED": "SOLO REFERENCIA · AFIRMACIONES SIN VERIFICAR",
"SOURCE GEOCONFIRMED": "FUENTE GEOCONFIRMADA",
"2021 historical reference versus 2026 post-event imagery; changes are cumulative and include the July 2025 Rasuwagadhi flood. Schematic downstream progression, not modeled arrival time; not an official hazard model.": "Referencia histórica de 2021 frente a imágenes posteriores al evento de 2026; los cambios son acumulativos e incluyen la inundación de Rasuwagadhi de julio de 2025. Avance esquemático aguas abajo, no un tiempo de llegada modelado; no es un modelo oficial de peligro.",
@@ -2025,7 +2025,7 @@
"Selected Space Mission": "Misión espacial seleccionada",
"{duration}s + {hold}s": "{duration} s + {hold} s",
"Configured Source": "Fuente configurada",
"subject": "sujeto",
"subject": "objetivo",
"{value}m": "{value} m",
"Google 3D tiles unavailable — check the key's API restrictions, quota, or network": "Teselas de Google 3D no disponibles: revisa las restricciones de API de la clave, la cuota o la red",
"Needs {envVars} — add it in Provider Settings — or a Cesium ion token for the ion-hosted route": "Necesita {envVars} — se añade en Ajustes de proveedores — o un token de Cesium ion para la ruta alojada en ion",
@@ -2041,7 +2041,7 @@
"zoom in to a street to open {name}": "acércate a una calle para abrir {name}",
"Google Street View": "Google Street View",
"GOOGLE STREET VIEW": "GOOGLE STREET VIEW",
"Google refused GOOGLE_MAPS_API_KEY for Street View — check that the Maps JavaScript API is enabled for it and this site is an allowed referrer": "Google rechazó GOOGLE_MAPS_API_KEY para Street View — comprueba que la clave tenga habilitada la API Maps JavaScript y que este sitio figure entre sus referentes HTTP permitidos",
"Google refused GOOGLE_MAPS_API_KEY for Street View — check that the Maps JavaScript API is enabled for it and this site is an allowed referrer": "Google rechazó GOOGLE_MAPS_API_KEY para Street View — comprueba que la clave tenga habilitada la API Maps JavaScript y que este sitio figure entre sus referentes HTTP (sitios web) permitidos",
"Street View did not answer — check the network, and that the Maps JavaScript API is enabled for GOOGLE_MAPS_API_KEY": "Street View no respondió — comprueba la red y que la API Maps JavaScript esté habilitada para GOOGLE_MAPS_API_KEY",
"click a street to open Street View": "haz clic en una calle para abrir Street View",
" or ": " o ",
@@ -2050,7 +2050,7 @@
"Zoom in to a street to open {names} here": "Acércate a una calle para abrir {names} aquí",
"radio tag|All": "Todas",
"Alternative": "Alternativa",
"Ambient": "Ambiental",
"Ambient": "Ambient",
"Blues": "Blues",
"Classical": "Clásica",
"Country": "Country",
@@ -2082,5 +2082,23 @@
"mapped matches within {km} km of the subject": "coincidencias mapeadas a menos de {km} km del objetivo",
"none mapped within {km} km; not a complete 250 km survey": "ninguna mapeada a menos de {km} km; no es un barrido completo de 250 km",
"mapped matches from the loaded viewport": "coincidencias mapeadas en la vista cargada",
"viewport feed is not a complete 250 km survey": "los datos de la vista no son un barrido completo de 250 km"
"viewport feed is not a complete 250 km survey": "los datos de la vista no son un barrido completo de 250 km",
"lane direction|left": "izquierdo",
"lane direction|right": "derecho",
"lane direction|slightly left": "izquierdo",
"lane direction|slightly right": "derecho",
"lane direction|sharply left": "del extremo izquierdo",
"lane direction|sharply right": "del extremo derecho",
"lane direction|straight": "central",
"{value}°N": "{value}°N",
"{value}°S": "{value}°S",
"{value}°E": "{value}°E",
"{value}°W": "{value}°W",
"fork direction|left": "a la izquierda",
"fork direction|right": "a la derecha",
"fork direction|slightly left": "ligeramente a la izquierda",
"fork direction|slightly right": "ligeramente a la derecha",
"fork direction|sharply left": "bruscamente a la izquierda",
"fork direction|sharply right": "bruscamente a la derecha",
"fork direction|straight": "recto"
}
+90 -72
View File
@@ -79,7 +79,7 @@
"Voice control — API key or ChatGPT OAuth": "Голосовое управление — ключ API или ChatGPT OAuth",
"Live ships, worldwide": "Суда в реальном времени по всему миру",
"Live active-fire detections": "Обнаружение активных пожаров в реальном времени",
"Real live traffic (keyless runs a simulation)": "Реальные пробки в реальном времени (без ключа — симуляция)",
"Real live traffic (keyless runs a simulation)": "Настоящие пробки в реальном времени (без ключа — симуляция)",
"Bing imagery map stacks + world terrain": "Снимки Bing + рельеф мира",
"Global Context navigation": "Навигация глобального контекста",
"Previous — prior visited contact in the 250 km window": "Назад — предыдущий посещённый контакт в радиусе 250 км",
@@ -233,7 +233,7 @@
"Operator unknown": "Оператор неизвестен",
"All": "Все",
"News": "Новости",
"Talk": "Ток-радио",
"Talk": "Разговорное",
"Weather / Emergency": "Погода / ЧС",
"Public Safety": "Общественная безопасность",
"Aviation / Marine": "Авиация / Море",
@@ -247,7 +247,7 @@
"Showing the full Starlink shell — click for the core catalog only": "Показана полная оболочка Starlink — нажмите, чтобы оставить только основной каталог",
"DENSE ···": "ПЛОТНО ···",
"DENSE ✕": "ПЛОТНО ✕",
"DENSE": "ПЛОТНО",
"DENSE": "ПЛОТНЫЙ",
"Syncing flow · Roads: {source}": "Синхронизация потока · Дороги: {source}",
"LIVE · Roads: {source} · Roads without flow hidden": "ОНЛАЙН · Дороги: {source} · Дороги без потока скрыты",
"LIVE · Roads: {source} · No flow roads in view": "ОНЛАЙН · Дороги: {source} · В кадре нет дорог с потоком",
@@ -324,10 +324,10 @@
"OFF": "ВЫКЛ",
"{city} · HDG {heading} · FOV {fov} · RANGE {range}m · {projection}{calBadge} · {provider}{status}": "{city} · КУРС {heading} · ОБЗОР {fov} · ДАЛЬН. {range} м · {projection}{calBadge} · {provider}{status}",
"{count} cameras loaded · click a camera to activate": {
"one": "Загружена {count} камера · нажмите на камеру, чтобы активировать",
"few": "Загружено {count} камеры · нажмите на камеру, чтобы активировать",
"many": "Загружено {count} камер · нажмите на камеру, чтобы активировать",
"other": "Загружено {count} камеры · нажмите на камеру, чтобы активировать"
"one": "Загружена {count} камера · щёлкните по камере, чтобы активировать",
"few": "Загружено {count} камеры · щёлкните по камере, чтобы активировать",
"many": "Загружено {count} камер · щёлкните по камере, чтобы активировать",
"other": "Загружено {count} камеры · щёлкните по камере, чтобы активировать"
},
"{count} cameras loaded · enable CCTV to activate": {
"one": "Загружена {count} камера · включите CCTV, чтобы активировать",
@@ -484,7 +484,7 @@
"Earthquakes (24h)": "Землетрясения (24 ч)",
"Satellites": "Спутники",
"Space Missions (30d)": "Космические миссии (30 дн.)",
"Street Traffic": "Уличный трафик",
"Street Traffic": "Дорожный трафик",
"CCTV": "CCTV",
"Radio": "Радио",
"Bikeshare": "Велошеринг",
@@ -501,7 +501,7 @@
"UNCERTAIN · {source} · lifecycle state requires reconciliation": "НЕОПРЕД. · {source} · требуется сверка состояния",
"{state} · {source} · {detail} · retry {seconds}s": "{state} · {source} · {detail} · повтор через {seconds} с",
"{state} · {source} · {detail}": "{state} · {source} · {detail}",
"never": "никогда",
"never": "не обновлялось",
"{source} · {loadingLabel}": "{source} · {loadingLabel}",
"{accepted} of {raw} records accepted": "принято записей: {accepted} из {raw}",
"incomplete snapshot": "неполный снимок",
@@ -798,7 +798,7 @@
"IMPORT": "ИМПОРТ",
"RUN LOG": "ЖУРНАЛ ЗАПУСКОВ",
"CALIBRATION": "КАЛИБРОВКА",
"Camera pose — click a value to type": "Поза камеры — нажмите на значение для ввода",
"Camera pose — click a value to type": "Поза камеры — щёлкните по значению, чтобы ввести",
"SCENE SUMMARY": "СВОДКА ПО СЦЕНЕ",
"CCTV camera": "Камера CCTV",
"Scene recipe": "Рецепт сцены",
@@ -882,19 +882,19 @@
"Enter to place the pin, Esc to cancel.": "Enter — поставить метку, Esc — отменить.",
"Click where the pin goes.": "Щёлкните, где поставить метку.",
"Click {count} more points.": {
"one": "Щёлкните ещё {count} точку.",
"few": "Щёлкните ещё {count} точки.",
"many": "Щёлкните ещё {count} точек.",
"other": "Щёлкните ещё {count} точки."
"one": "Отметьте ещё {count} точку.",
"few": "Отметьте ещё {count} точки.",
"many": "Отметьте ещё {count} точек.",
"other": "Отметьте ещё {count} точки."
},
"Those points are in a line — move one off it to enclose an area.": "Точки лежат на одной линии — сдвиньте одну, чтобы получилась площадь.",
"Those points are in a line — move one off it to enclose an area.": "Точки лежат на одной линии — сдвиньте одну из них, чтобы образовалась замкнутая область.",
"That line has no length — click somewhere further away.": "У линии нет длины — щёлкните дальше.",
" · {max}-point limit reached": " · достигнут предел в {max} точек",
" · {max}-point limit reached": " · лимит точек: {max}",
"{measure} · double-click or Enter to finish, Backspace undoes, Esc cancels.{full}": "{measure} · двойной щелчок или Enter — завершить, Backspace — отменить точку, Esc — отменить.{full}",
"That point is off the globe — click on the world.": "Эта точка вне глобуса — щёлкните по Земле.",
"That shape could not be placed.": "Не удалось разместить фигуру.",
"Board cleared.": "Доска очищена.",
"Draw on the world — click vertices, double-click or Enter to finish, Esc to cancel": "Рисовать на карте мира — щёлкайте вершины, двойной щелчок или Enter — завершить, Esc — отменить",
"Draw on the world — click vertices, double-click or Enter to finish, Esc to cancel": "Рисовать на карте мира — щёлкайте по вершинам, двойной щелчок или Enter — завершить, Esc — отменить",
"Draw": "Рисование",
"Shape": "Фигура",
"Shape to draw": "Фигура для рисования",
@@ -961,10 +961,10 @@
"other": "{n} снимка в последовательности · Esc — сбросить"
},
"{n} sequences in view · click a line for its photos": {
"one": "{n} последовательность в кадре · щёлкните линию, чтобы открыть снимки",
"few": "{n} последовательности в кадре · щёлкните линию, чтобы открыть снимки",
"many": "{n} последовательностей в кадре · щёлкните линию, чтобы открыть снимки",
"other": "{n} последовательности в кадре · щёлкните линию, чтобы открыть снимки"
"one": "{n} последовательность в кадре · щёлкните по линии, чтобы открыть снимки",
"few": "{n} последовательности в кадре · щёлкните по линии, чтобы открыть снимки",
"many": "{n} последовательностей в кадре · щёлкните по линии, чтобы открыть снимки",
"other": "{n} последовательности в кадре · щёлкните по линии, чтобы открыть снимки"
},
"STREET LEVEL": "УЛИЧНЫЕ СНИМКИ",
"Expand the street-level view (Esc shrinks it)": "Развернуть уличный снимок (Esc сворачивает)",
@@ -972,7 +972,7 @@
"FIT": "ВПИСАТЬ",
"Fit: show the whole photo, with dark bars where its shape differs from the frame": "Вписать: показать снимок целиком, с тёмными полосами там, где его форма не совпадает с рамкой",
"FILL": "ЗАПОЛНИТЬ",
"Fill: fill the frame edge to edge, cropping the photo": "Заполнить: растянуть на всю рамку, обрезав снимок",
"Fill: fill the frame edge to edge, cropping the photo": "Заполнить: заполнить рамку целиком, обрезав края снимка",
"Camera follows view": "Камера следует за видом",
"FOLLOW": "СЛЕДИТЬ",
"Close the image and deselect it on the map": "Закрыть снимок и снять выделение на карте",
@@ -996,7 +996,7 @@
"{provider} · EMBEDDED SOURCE": "{provider} · ВСТРОЕННЫЙ ИСТОЧНИК",
"OPEN ORIGINAL ↗": "ОТКРЫТЬ ОРИГИНАЛ ↗",
"{provider} media: {source}": "Медиа {provider}: {source}",
"{provider} · PROVIDER CONTROLS": "{provider} · ПЛЕЕР ПРОВАЙДЕРА",
"{provider} · PROVIDER CONTROLS": "{provider} · УПРАВЛЕНИЕ ПРОВАЙДЕРА",
"YOUTUBE {state} · OPEN ORIGINAL": "YOUTUBE {state} · ОТКРЫТЬ ОРИГИНАЛ",
"Facebook player API did not initialize.": "API плеера Facebook не инициализировался.",
"Facebook player API could not load.": "Не удалось загрузить API плеера Facebook.",
@@ -1010,10 +1010,10 @@
"Preloading {provider} media": "Предзагрузка медиа {provider}",
"LOADING X POST…": "ЗАГРУЗКА ПОСТА X…",
"The X post is unavailable or cannot be embedded.": "Пост X недоступен или не может быть встроен.",
"X POST · PROVIDER CONTROLS": "ПОСТ X · ВИДЖЕТ ПРОВАЙДЕРА",
"X POST · PROVIDER CONTROLS": "ПОСТ X · УПРАВЛЕНИЕ ПРОВАЙДЕРА",
"{reason} OPEN ORIGINAL.": "{reason} ОТКРОЙТЕ ОРИГИНАЛ.",
"X embed unavailable": "Встраивание X недоступно",
"FACEBOOK · PROVIDER CONTROLS": "FACEBOOK · ПЛЕЕР ПРОВАЙДЕРА",
"FACEBOOK · PROVIDER CONTROLS": "FACEBOOK · УПРАВЛЕНИЕ ПРОВАЙДЕРА",
"Facebook embed unavailable": "Встраивание Facebook недоступно",
"AUTOPLAY BLOCKED · USE PROVIDER CONTROLS": "АВТОВОСПРОИЗВЕДЕНИЕ ЗАБЛОКИРОВАНО · ИСПОЛЬЗУЙТЕ УПРАВЛЕНИЕ ПРОВАЙДЕРА",
"Embedded {provider} media for {source}": "Встроенное медиа {provider}: {source}",
@@ -1023,8 +1023,8 @@
"Historical reference and post-event image divider": "Разделитель исторического снимка и снимка после события",
"A historical reference {before} percent, B post-event {after} percent": "A — исторический снимок: {before}%, B — после события: {after}%",
"■ RELEASE CAMERA": "■ ОСВОБОДИТЬ КАМЕРУ",
"Seek Nepal scene clock": "Перемотка часов непальской сцены",
"NEPAL SCENE CLOCK": "ЧАСЫ НЕПАЛЬСКОЙ СЦЕНЫ",
"Seek Nepal scene clock": "Перемотка времени сцены в Непале",
"NEPAL SCENE CLOCK": "ВРЕМЯ СЦЕНЫ В НЕПАЛЕ",
"… PLAYING SHOT": "… ИДЁТ КАДР",
"▶ PLAY SHOT": "▶ ПУСК КАДРА",
"Ⅱ PAUSE": "Ⅱ ПАУЗА",
@@ -1050,7 +1050,7 @@
"Play reconstruction": "Воспроизвести реконструкцию",
"Load previous scene shot": "Загрузить предыдущий кадр сцены",
"Load next scene shot": "Загрузить следующий кадр сцены",
"SCHEMATIC CORRIDOR, NOT MODELED ARRIVAL TIME.": "СХЕМАТИЧЕСКИЙ КОРИДОР, НЕ МОДЕЛЬ ВРЕМЕНИ ПРИХОДА.",
"SCHEMATIC CORRIDOR, NOT MODELED ARRIVAL TIME.": "СХЕМАТИЧЕСКИЙ КОРИДОР, А НЕ МОДЕЛЬ ВРЕМЕНИ ДОБЕГАНИЯ ПАВОДКА.",
"Rasuwa · 26 Aug 2026": "Rasuwa · 26 авг. 2026",
"Event reconstruction": "Реконструкция события",
"INITIATION": "ЗАРОЖДЕНИЕ",
@@ -1079,7 +1079,7 @@
"SCHEMATIC CORRIDOR": "СХЕМАТИЧЕСКИЙ КОРИДОР",
"2021 HISTORICAL REFERENCE / 2026 POST-EVENT": "2021 ИСТОРИЧЕСКИЙ СНИМОК / 2026 ПОСЛЕ СОБЫТИЯ",
"Historical reference and post-event image split": "Сравнение исторического снимка и снимка после события",
"RECONSTRUCTION CLOCK": "ЧАСЫ РЕКОНСТРУКЦИИ",
"RECONSTRUCTION CLOCK": "ВРЕМЯ РЕКОНСТРУКЦИИ",
"Schematic downstream progression": "Схематическое продвижение вниз по течению",
"Story beat navigation": "Навигация по этапам сюжета",
"Previous story beat": "Предыдущий этап сюжета",
@@ -1164,7 +1164,7 @@
"None on screen — nearby cameras are outside the view": "На экране нет — ближайшие камеры вне поля зрения",
"ALPR camera": "Камера ALPR",
"OpenStreetMap · community mapped": "OpenStreetMap · нанесено сообществом",
"Atlantic and eastern/central North Pacific; not worldwide cyclone coverage.": "Атлантика и восточная/центральная часть северной Пацифики; покрытие циклонов не глобальное.",
"Atlantic and eastern/central North Pacific; not worldwide cyclone coverage.": "Атлантика и восточная/центральная часть северного Тихого океана; покрытие циклонов не глобальное.",
"Potential tropical cyclone": "Потенциальный тропический циклон",
"Hurricane": "Ураган",
"Tropical storm": "Тропический шторм",
@@ -1188,7 +1188,7 @@
"No active NHC/CPHC systems": "Нет активных систем NHC/CPHC",
"Advisories unavailable": "Сводки недоступны",
"Cyclones · NHC / CPHC": "Циклоны · NHC / CPHC",
"Atlantic · E/C Pacific": "Атлантика · вост./центр. Пацифика",
"Atlantic · E/C Pacific": "Атлантика · вост./центр. Тихий океан",
"{storms} · {name} selected": "{storms} · выбран {name}",
"Official advisory ↗": "Официальная сводка ↗",
"Active NHC and CPHC cyclone advisories": "Действующие сводки NHC и CPHC о циклонах",
@@ -1200,10 +1200,10 @@
"{mode} — reroute for {modeLower}": "{mode} — перестроить маршрут: {modeLower}",
"CLICK MAP": "ЩЁЛКНИТЕ ПО КАРТЕ",
"SET A": "ЗАДАТЬ A",
"Click a spot on the globe to place A (click again to cancel)": "Щёлкните точку на глобусе, чтобы поставить A (повторный щелчок — отмена)",
"Click a spot on the globe to place A (click again to cancel)": "Щёлкните по точке на глобусе, чтобы поставить A (повторный щелчок — отмена)",
"Then click the globe to place the start": "Затем щёлкните по глобусу, чтобы поставить начало",
"SET B": "ЗАДАТЬ B",
"Click a spot on the globe to place B (click again to cancel)": "Щёлкните точку на глобусе, чтобы поставить B (повторный щелчок — отмена)",
"Click a spot on the globe to place B (click again to cancel)": "Щёлкните по точке на глобусе, чтобы поставить B (повторный щелчок — отмена)",
"Then click the globe to place the destination": "Затем щёлкните по глобусу, чтобы поставить пункт назначения",
"Swap A and B": "Поменять A и B местами",
"FLY ···": "ПОЛЁТ ···",
@@ -1212,7 +1212,7 @@
"Fly the camera along the route": "Пролететь камерой по маршруту",
"Place A and B first": "Сначала поставьте A и B",
"Remove the route and both markers": "Удалить маршрут и обе метки",
"press Escape twice to leave Draw": "дважды нажмите Escape, чтобы выйти из режима «Рисование»",
"press Escape twice to leave Draw": "дважды нажмите Esc, чтобы выйти из режима «Рисование»",
"{name} is active — turn {name} off, then set {endpoint}": "Активно: {name} — выключите {name}, затем задайте {endpoint}",
"{name} is active — {leave}, then set {endpoint}": "Активно: {name} — {leave}, затем задайте {endpoint}",
"Only the first {count} turns of this route are shown": "Показаны только первые повороты маршрута: {count}",
@@ -1220,7 +1220,7 @@
"OSM routing": "Маршрутизация OSM",
"DRIVE": "АВТО",
"Drive": "На машине",
"Another map tool is using clicks — close it, then SET A again": "Щелчки занимает другой инструмент карты — закройте его и снова нажмите ЗАДАТЬ A",
"Another map tool is using clicks — close it, then SET A again": "Щелчки перехватывает другой инструмент карты — закройте его и снова нажмите «ЗАДАТЬ A»",
"WALK": "ПЕШКОМ",
"Walk": "Пешком",
"Routing…": "Построение маршрута…",
@@ -1267,7 +1267,7 @@
"Waiting for observation": "Ожидание наблюдения",
"{detail} · synced": "{detail} · синхр.",
"{detail} · nearest": "{detail} · ближайший",
"RADAR REFLECTIVITY · dBZ": "ОТРАЖАЕМОСТЬ РАДАРА · dBZ",
"RADAR REFLECTIVITY · dBZ": "РАДИОЛОК. ОТРАЖАЕМОСТЬ · dBZ",
"LIGHTNING DENSITY · 15 min accumulation": "ПЛОТНОСТЬ МОЛНИЙ · накопление за 15 мин",
"GLOBAL INFRARED · hourly": "ГЛОБАЛЬНЫЙ ИК · ежечасно",
"GOES INFRARED · ~5 min": "GOES ИК · ~5 мин",
@@ -1282,7 +1282,7 @@
"60°S–60°N · typically 2–3 h delayed": "60° ю. ш.–60° с. ш. · обычно задержка 2–3 ч",
"North America · infrared imagery": "Северная Америка · ИК-снимки",
"Reduced motion · history playback unavailable": "Уменьшение движения · воспроизведение истории недоступно",
"Reduced motion · manual history available": "Уменьшение движения · доступна ручная история",
"Reduced motion · manual history available": "Уменьшение движения · историю можно листать вручную",
"Rain radar · US": "Радар осадков · США",
"Lightning density · 15 min": "Плотность молний · 15 мин",
"Satellite clouds": "Спутниковая облачность",
@@ -1300,7 +1300,7 @@
"GOES regional clouds; approximately 5-minute updates": "Региональная облачность GOES; обновление примерно каждые 5 мин",
"Clouds only": "Только облака",
"Dim everything but the bright, cold cloud tops; a brightness filter, not a cloud mask": "Затемнить всё, кроме ярких холодных вершин облаков; фильтр яркости, а не маска облачности",
"Full": "Полное",
"Full": "Полный",
"The complete infrared image at the chosen opacity": "Полное ИК-изображение с выбранной непрозрачностью",
"Soft": "Мягко",
"Vivid": "Ярко",
@@ -1309,7 +1309,7 @@
"View Americas & Pacific": "Показать Америку и Тихий океан",
"View coverage": "Показать зону покрытия",
"{value} strikes/km²/min ×10³ (15-minute density)": "{value} разрядов/км²/мин ×10³ (плотность за 15 мин)",
"{value} dBZ radar reflectivity": "Отражаемость радара: {value} dBZ",
"{value} dBZ radar reflectivity": "Радиолокационная отражаемость: {value} dBZ",
"STALE · cached source metadata": "УСТАРЕЛ · метаданные источника из кэша",
"Map center is outside source coverage": "Центр карты вне зоны покрытия источника",
"NOAA/NWS 15-minute lightning density derived from Vaisala NLDN/GLD360. Coverage 110°E across the Pacific/Americas to 0°, 25°S–80°N. Not a live strike count, global coverage or a safety warning.": "15-минутная плотность молний NOAA/NWS на основе Vaisala NLDN/GLD360. Покрытие — от 110° в. д. через Тихий океан и Америку до 0°, 25° ю. ш.–80° с. ш. Это не подсчёт разрядов в реальном времени, не глобальное покрытие и не предупреждение об опасности.",
@@ -1356,7 +1356,7 @@
"UNITS": "ЕДИНИЦЫ",
"MOTION": "ДВИЖЕНИЕ",
"Forecast": "Прогноз",
"Interpolated model forecast on an approximately 1° grid. Broad weather patterns, not a street-level measurement.": "Интерполированный модельный прогноз на сетке около 1°. Крупные погодные закономерности, а не измерение на уровне улицы.",
"Interpolated model forecast on an approximately 1° grid. Broad weather patterns, not a street-level measurement.": "Интерполированный модельный прогноз на сетке около 1°. Общая погодная обстановка, а не измерение на уровне улицы.",
"No surface reading": "Нет приземных данных",
"Aim the map center at Earth": "Наведите центр карты на Землю",
" · calm": " · штиль",
@@ -1375,7 +1375,7 @@
"Layers refused: {layers}": "Слои отклонены: {layers}",
"Scene {n}": "Сцена {n}",
"Cannot update {scene}: shot inventory changed": "Не удалось обновить {scene}: изменился состав кадров",
"Cannot update {scene}: evidence beats changed": "Не удалось обновить {scene}: изменились этапы доказательств",
"Cannot update {scene}: evidence beats changed": "Не удалось обновить {scene}: изменились этапы свидетельств",
"Cannot update {scene}: shot bindings are incomplete": "Не удалось обновить {scene}: привязки кадров неполные",
"Updated {count} shots: {scene}": {
"one": "Обновлён {count} кадр: {scene}",
@@ -1394,7 +1394,7 @@
"Action complete": "Действие выполнено",
"Action unavailable or cancelled": "Действие недоступно или отменено",
"Scene actions": "Действия сцены",
"Bhote Koshi Evidence Sequence": "Последовательность доказательств: Bhote Koshi",
"Bhote Koshi Evidence Sequence": "Последовательность свидетельств: Bhote Koshi",
"Nepal Flood Incident": "Наводнение в Непале",
"{count} scenes": {
"one": "{count} сцена",
@@ -1487,8 +1487,8 @@
"Infrastructure": "Инфраструктура",
"Events": "События",
"Weather": "Погода",
"LOCATED": "ОПРЕДЕЛЕНО",
"LOCATE": "ОПРЕДЕЛИТЬ",
"LOCATED": "ОПРЕДЕЛЕНА",
"LOCATE": "ГЕОПОЗИЦИЯ",
"IDLE": "ОЖИДАНИЕ",
"TUNING": "НАСТРОЙКА",
"STREAMING": "ПРИЁМ",
@@ -1518,7 +1518,7 @@
},
"DISCONNECT": "ОТКЛЮЧИТЬ",
"CONNECT": "ПОДКЛЮЧИТЬ",
"LOCATING…": "ОПРЕДЕЛЕНИЕ…",
"LOCATING…": "ОПРЕДЕЛЯЮ…",
"Drag to resize · double-click the header to snap back": "Перетащите, чтобы изменить размер · двойной щелчок по заголовку — вернуть на место",
"CH {index} / {total}": "КАН. {index} / {total}",
"Station unavailable after directory refresh": "Станция недоступна после обновления каталога",
@@ -1537,9 +1537,9 @@
"Imagery days, newest first · arrows move, S or A and B pin": "Дни со снимками, сначала новые · стрелки — перемещение, S или A и B — закрепить",
"On the map": "На карте",
"Mode": "Режим",
"Imagery on Esri · Google 3D returns when cleared": "Снимки поверх Esri · после очистки вернётся Google 3D",
"Imagery on Esri · Google 3D returns when cleared": "Снимки на Esri · сброс вернёт Google 3D",
"Imagery opacity": "Непрозрачность снимков",
"SWAP": "СМЕНА",
"SWAP": "ПОМЕНЯТЬ",
"VS BASEMAP": "VS ПОДЛОЖКА",
"Trade the two sides of the divider": "Поменять местами стороны разделителя",
"A / B": "A / B",
@@ -1618,7 +1618,7 @@
"Select a box or use the view": "Выделите область или используйте текущий вид",
"Searching the last 30 days": "Поиск за последние 30 дней",
"No days to show for this box": "Для этой области нет дней для показа",
"Drag the divider · SWAP trades sides": "Перетащите разделитель · СМЕНА меняет стороны",
"Drag the divider · SWAP trades sides": "Перетащите разделитель · «ПОМЕНЯТЬ» меняет стороны местами",
"Export failed · {error}": "Ошибка экспорта · {error}",
"← → preview · A or B pins the focused day": "← → просмотр · A или B закрепляет выбранный день",
"← → preview the other side · A or B pins it": "← → просмотр другой стороны · A или B закрепляет её",
@@ -1645,7 +1645,7 @@
"WX": "ПОГОДА",
"DIRECTORY: RADIO BROWSER": "КАТАЛОГ: RADIO BROWSER",
"Use your location for faster ADS-B position decoding": "Использовать ваше местоположение для ускорения декодирования позиций ADS-B",
"CHANGE DEVICE": "СМЕНИТЬ УСТРОЙСТВО",
"CHANGE DEVICE": "СМЕНИТЬ",
"Choose a different RTL-SDR or receiver channel": "Выбрать другой RTL-SDR или канал приёмника",
"TUNE": "НАСТРОИТЬ",
"◀ SEEK": "◀ ПОИСК",
@@ -1691,14 +1691,14 @@
"Lightning density": "Плотность молний",
"LATEST · newest per product": "ПОСЛЕДНИЕ · самые свежие по каждому продукту",
"Forecast · valid {valid} · issued {issued}": "Прогноз · действует на {valid} · выпущен {issued}",
"{detail} · Does not follow history": "{detail} · Не следует истории",
"{detail} · Does not follow history": "{detail} · не следует за историей",
"Forecast · valid {valid}": "Прогноз · действует на {valid}",
"{time} · {minutes} min ago": "{time} · {minutes} мин назад",
"Active weather": "Активная погода",
"Active weather": "Активные погодные слои",
"MINI": "МИНИ",
"STD": "СТД",
"standard": "стандартную",
"mini": "mini",
"mini": "мини",
"COST UNKNOWN": "СТОИМОСТЬ НЕИЗВЕСТНА",
"ChatGPT OAuth session: {responses} response(s), {input} input and {output} output tokens, {captions} caption transcription(s) reported.": "Сессия ChatGPT OAuth: ответов — {responses}, входных токенов — {input}, выходных токенов — {output}, транскрипций субтитров — {captions}.",
"USD cost and the API spend cap are unavailable for this auth mode.": "Стоимость в USD и лимит расходов API недоступны в этом режиме авторизации.",
@@ -1714,11 +1714,11 @@
"unavailable": "недоступен",
"{label} on": "{label}: вкл.",
"{label} off": "{label}: выкл.",
"Frame aircraft": "Кадр: самолёты",
"Frame military aircraft": "Кадр: военные самолёты",
"Frame ships": "Кадр: суда",
"Frame satellites": "Кадр: спутники",
"Frame contacts": "Кадр: контакты",
"Frame aircraft": "Показать самолёты в кадре",
"Frame military aircraft": "Показать военные самолёты в кадре",
"Frame ships": "Показать суда в кадре",
"Frame satellites": "Показать спутники в кадре",
"Frame contacts": "Показать контакты в кадре",
"{count} aircraft in frame": {
"one": "{count} самолёт в кадре",
"few": "{count} самолёта в кадре",
@@ -1763,7 +1763,7 @@
"{origin} to {destination}": "{origin} → {destination}",
"from {origin}": "откуда: {origin}",
"to {destination}": "куда: {destination}",
"Registration {registration}": "Регистрация {registration}",
"Registration {registration}": "Регистрационный номер: {registration}",
"Route {route}": "Маршрут {route}",
"View state": "Состояние вида",
"Marked {count} places": {
@@ -1780,9 +1780,9 @@
"Mark {targets}": "Отметить {targets}",
"Fly to {place}": "Перелёт: {place}",
"Nearest aircraft to {place}": "Ближайшие самолёты: {place}",
"Read the view": "Прочитать вид",
"Read the view": "Осмотреть видимую область",
"Check view state": "Проверить состояние вида",
"Frame {target}": "Кадр: {target}",
"Frame {target}": "Показать в кадре: {target}",
"Finding places": "Поиск мест",
"Tracing outline": "Построение контура",
"Looking up place": "Поиск места",
@@ -1890,7 +1890,7 @@
"At the end of the road, continue": "В конце дороги продолжайте движение",
"At the end of the road, continue onto {road}": "В конце дороги продолжайте движение по {road}",
"Keep {direction} at the fork": "На развилке держитесь {direction}",
"Keep {direction} at the fork onto {road}": "На развилке держитесь {direction} на {road}",
"Keep {direction} at the fork onto {road}": "На развилке держитесь {direction}, чтобы выехать на {road}",
"Continue at the fork": "На развилке продолжайте движение",
"Continue at the fork onto {road}": "На развилке продолжайте движение по {road}",
"Merge {direction}": "Перестройтесь {direction}",
@@ -1915,8 +1915,8 @@
"At the roundabout, continue onto {road}": "На кольце продолжайте движение на {road}",
"Exit the roundabout": "Съезжайте с кольца",
"Exit the roundabout onto {road}": "Съезжайте с кольца на {road}",
"Use the {direction} lane": "Займите полосу для движения {direction}",
"Use the {direction} lane onto {road}": "Займите полосу для движения {direction} на {road}",
"Use the {direction} lane": "Займите {direction} полосу",
"Use the {direction} lane onto {road}": "Займите {direction} полосу, чтобы выехать на {road}",
"voice|OFF": "ВЫКЛ",
"voice|CONNECTING": "СВЯЗЬ…",
"voice|LISTENING": "СЛУШАЮ",
@@ -1951,7 +1951,7 @@
"N/A": "Н/Д",
"{label} · {radius} AIR/SEA WINDOW": "{label} · ОКНО ВОЗДУХ/МОРЕ {radius}",
"{scope} · INSTALLATIONS {coverage}": "{scope} · ОБЪЕКТЫ: {coverage}",
"{source} · LOCATION QUERY · RECENT": "{source} · ЗАПРОС ПО МЕСТУ · СВЕЖЕЕ",
"{source} · LOCATION QUERY · RECENT": "{source} · ЗАПРОС ПО МЕСТУ · НЕДАВНИЕ",
"ft": "фт",
"kts": "уз",
"PAUSE": "ПАУЗА",
@@ -1968,7 +1968,7 @@
"SNAPSHOT": "СНИМОК",
"LIVE": "ОНЛАЙН",
"UPSTREAM": "ИСТОЧНИК",
"SYNTHETIC": "СИНТЕТИКА",
"SYNTHETIC": "СИМУЛЯЦИЯ",
"CONFIGURED": "НАСТРОЕН",
"SEED": "КАТАЛОГ",
"Live HLS connected": "Поток HLS подключён",
@@ -2002,7 +2002,7 @@
"SOURCE CREDITED · LOCATION UNRESOLVED": "АВТОР УКАЗАН · МЕСТО НЕ УСТАНОВЛЕНО",
"REFERENCE ONLY · CLAIMS UNVERIFIED": "ТОЛЬКО ДЛЯ СПРАВКИ · ЗАЯВЛЕНИЯ НЕ ПРОВЕРЕНЫ",
"SOURCE GEOCONFIRMED": "ИСТОЧНИК ГЕОПОДТВЕРЖДЁН",
"2021 historical reference versus 2026 post-event imagery; changes are cumulative and include the July 2025 Rasuwagadhi flood. Schematic downstream progression, not modeled arrival time; not an official hazard model.": "Исторический снимок 2021 года в сравнении со снимками 2026 года после события; изменения накопительные и включают паводок в Rasuwagadhi в июле 2025 года. Схематическое продвижение вниз по течению, а не смоделированное время прихода; не официальная модель опасности.",
"2021 historical reference versus 2026 post-event imagery; changes are cumulative and include the July 2025 Rasuwagadhi flood. Schematic downstream progression, not modeled arrival time; not an official hazard model.": "Исторический снимок 2021 года в сравнении со снимками 2026 года после события; изменения накоплены за весь период и включают паводок в Rasuwagadhi в июле 2025 года. Схематическое продвижение вниз по течению, а не смоделированное время добегания паводка; не официальная модель опасности.",
"Immediate collapse viewpoint": "Точка обзора у места обрушения",
"Collapse viewpoint": "Обзор обрушения",
"Debris-dammed lake": "Озеро, запруженное обломками",
@@ -2052,7 +2052,7 @@
"Globe imagery unavailable": "Снимки глобуса недоступны",
"Globe field image unavailable": "Изображение поля на глобусе недоступно",
"status chip|UNAVAILABLE": "НЕДОСТ.",
"Uses registered content or linked media. Those external files are not included in a scene bundle. Their original notices still apply.": "Используется зарегистрированный контент или связанные медиафайлы. Эти внешние файлы не входят в архив сцены. Их исходные уведомления по-прежнему действуют.",
"Uses registered content or linked media. Those external files are not included in a scene bundle. Their original notices still apply.": "Используется зарегистрированный контент или связанные медиафайлы. Эти внешние файлы не входят в архив сцены. Их исходные условия использования по-прежнему действуют.",
"{state} {layers}": "{state}: {layers}",
"Selected Space Mission": "Выбранная космическая миссия",
"{duration}s + {hold}s": "{duration} с + {hold} с",
@@ -2062,20 +2062,20 @@
"Google 3D tiles unavailable — check the key's API restrictions, quota, or network": "Тайлы Google 3D недоступны — проверьте ограничения API ключа, квоту или сеть",
"Needs {envVars} — add it in Provider Settings — or a Cesium ion token for the ion-hosted route": "Нужен {envVars} — добавьте его в «Настройках провайдеров» — или токен Cesium ion для маршрута через ion",
"Comparison in use by another scene": "Сравнение занято другой сценой",
"A location reading needs a loaded forecast and the Earth at the center of the view.": "Для показания в точке нужен загруженный прогноз и Земля в центре вида.",
"A location reading needs a loaded forecast and the Earth at the center of the view.": "Чтобы получить данные в точке, загрузите прогноз и поместите Землю в центр экрана.",
"{mode} {band} {locality} | {region} | ALT {alt} | WINDOW {window} | SUN {sun}° | ONA {ona}° | {zone}": "{mode} · {band} · {locality} | {region} | ALT {alt} | ОКНО {window} | SUN {sun}° | ONA {ona}° | {zone}",
"light {source} to use your {name} key": "включите {source}, чтобы использовать ваш ключ {name}",
"light {source}": "включите {source}",
", or ": ", или ",
"{requirement}, or {offer}": "{requirement}, или {offer}",
"The photorealistic 3D planet, place search + Street View": "Фотореалистичная 3D-планета, поиск мест + Просмотр улиц",
"{name} needs the Google 3D map: choose it under MAP SOURCE": "Для {name} нужна карта Google 3D: выберите её в разделе «ИСТОЧНИК КАРТЫ»",
"{name} needs the Google 3D map: choose it under MAP SOURCE": "{name}: нужна карта Google 3D — выберите её в разделе «ИСТОЧНИК КАРТЫ»",
"zoom in to a street to open {name}": "приблизьтесь к улице, чтобы открыть {name}",
"Google Street View": "Google Просмотр улиц",
"GOOGLE STREET VIEW": "GOOGLE ПРОСМОТР УЛИЦ",
"Google refused GOOGLE_MAPS_API_KEY for Street View — check that the Maps JavaScript API is enabled for it and this site is an allowed referrer": "Google отклонил GOOGLE_MAPS_API_KEY для Просмотра улиц — проверьте, что для ключа включён Maps JavaScript API, а этот сайт есть среди разрешённых referrer",
"Google refused GOOGLE_MAPS_API_KEY for Street View — check that the Maps JavaScript API is enabled for it and this site is an allowed referrer": "Google отклонил GOOGLE_MAPS_API_KEY для Просмотра улиц — проверьте, что для ключа включён Maps JavaScript API, а адрес этого сайта есть в списке разрешённых (HTTP referrer)",
"Street View did not answer — check the network, and that the Maps JavaScript API is enabled for GOOGLE_MAPS_API_KEY": "Просмотр улиц не ответил — проверьте сеть и что для GOOGLE_MAPS_API_KEY включён Maps JavaScript API",
"click a street to open Street View": "нажмите на улицу, чтобы открыть Просмотр улиц",
"click a street to open Street View": "щёлкните по улице, чтобы открыть Просмотр улиц",
" or ": " или ",
"OPEN {labels}": "ОТКРЫТЬ {labels}",
"Open {names} at the centre of the view": "Открыть {names} в центре вида",
@@ -2114,5 +2114,23 @@
"mapped matches within {km} km of the subject": "совпадения на карте в радиусе {km} км от объекта",
"none mapped within {km} km; not a complete 250 km survey": "на карте нет в радиусе {km} км; это не полный обзор 250 км",
"mapped matches from the loaded viewport": "совпадения на карте в загруженной области",
"viewport feed is not a complete 250 km survey": "данные видимой области — не полный обзор 250 км"
"viewport feed is not a complete 250 km survey": "данные видимой области — не полный обзор 250 км",
"fork direction|left": "левее",
"fork direction|right": "правее",
"fork direction|slightly left": "чуть левее",
"fork direction|slightly right": "чуть правее",
"fork direction|sharply left": "левее",
"fork direction|sharply right": "правее",
"fork direction|straight": "прямо",
"lane direction|left": "левую",
"lane direction|right": "правую",
"lane direction|slightly left": "левую",
"lane direction|slightly right": "правую",
"lane direction|sharply left": "крайнюю левую",
"lane direction|sharply right": "крайнюю правую",
"lane direction|straight": "среднюю",
"{value}°N": "{value}° с. ш.",
"{value}°S": "{value}° ю. ш.",
"{value}°E": "{value}° в. д.",
"{value}°W": "{value}° з. д."
}
+2 -2
View File
@@ -5,6 +5,7 @@
"ANIME",
"ASIA",
"AUTO",
"Ambient",
"Anime",
"BRG {value}°",
"BRG —",
@@ -122,7 +123,6 @@
"R&B",
"REC",
"VS",
"WHOT/BHOT",
"mini"
"WHOT/BHOT"
]
}
+2 -2
View File
@@ -14,14 +14,14 @@ import {
CYCLONE_OVERLAY_SOURCE_ID,
cycloneStormIdFromEntryId,
} from './labels.js';
import { t, tn, msg } from '../../i18n/index.js';
import { formatUtcDayMonth, t, tn, msg } from '../../i18n/index.js';
import { formatQuantity } from '../../ui/unitLabels.js';
// "10-12 15:00 UTC" never breaks across lines: no-break spaces, and a word
// joiner after the hyphen (JetBrains Mono has no U+2011 non-breaking hyphen).
const utc = (value) =>
value
? `${value.slice(5, 16).replace('-', '-\u2060').replace('T', '\u00a0')}\u00a0UTC`
? `${formatUtcDayMonth(value).replace('-', '-\u2060')}\u00a0${value.slice(11, 16)}\u00a0UTC`
: t('Unavailable');
const COVERAGE = msg(
'Atlantic and eastern/central North Pacific; not worldwide cyclone coverage.',
+57 -6
View File
@@ -132,6 +132,53 @@ function directionWord(modifier) {
}
}
/**
* The side to keep at a fork. English reuses the turn words; a language may
* need another form here ("держитесь левее", not "держитесь налево").
*/
function forkWord(modifier) {
switch (modifier) {
case 'left':
return t('left', { context: 'fork direction' });
case 'right':
return t('right', { context: 'fork direction' });
case 'slight left':
return t('slightly left', { context: 'fork direction' });
case 'slight right':
return t('slightly right', { context: 'fork direction' });
case 'sharp left':
return t('sharply left', { context: 'fork direction' });
case 'sharp right':
return t('sharply right', { context: 'fork direction' });
case 'straight':
return t('straight', { context: 'fork direction' });
default:
return directionWord(modifier);
}
}
/** The lane to use, as an adjective where a language needs one ("левую полосу"). */
function laneWord(modifier) {
switch (modifier) {
case 'left':
return t('left', { context: 'lane direction' });
case 'right':
return t('right', { context: 'lane direction' });
case 'slight left':
return t('slightly left', { context: 'lane direction' });
case 'slight right':
return t('slightly right', { context: 'lane direction' });
case 'sharp left':
return t('sharply left', { context: 'lane direction' });
case 'sharp right':
return t('sharply right', { context: 'lane direction' });
case 'straight':
return t('straight', { context: 'lane direction' });
default:
return directionWord(modifier);
}
}
/** "1st", "2nd", … for a roundabout exit. */
function exitOrdinal(exit) {
const number = formatNumber(exit);
@@ -211,10 +258,12 @@ export function directionsInstruction(step) {
? t('At the end of the road, continue onto {road}', values)
: t('At the end of the road, continue');
case 'fork':
if (direction)
if (direction) {
const fork = { road, direction: forkWord(modifier) };
return road
? t('Keep {direction} at the fork onto {road}', values)
: t('Keep {direction} at the fork', values);
? t('Keep {direction} at the fork onto {road}', fork)
: t('Keep {direction} at the fork', fork);
}
return road
? t('Continue at the fork onto {road}', values)
: t('Continue at the fork');
@@ -266,10 +315,12 @@ export function directionsInstruction(step) {
? t('Exit the roundabout onto {road}', values)
: t('Exit the roundabout');
case 'use lane':
if (direction)
if (direction) {
const lane = { road, direction: laneWord(modifier) };
return road
? t('Use the {direction} lane onto {road}', values)
: t('Use the {direction} lane', values);
? t('Use the {direction} lane onto {road}', lane)
: t('Use the {direction} lane', lane);
}
return road
? t('Continue onto {road}', values)
: t('Continue', { context: 'maneuver' });
+9 -2
View File
@@ -2,7 +2,7 @@ import {
accentForVesselType,
normalizeVesselType,
} from '../../data/vesselLabels.js';
import { t } from '../../i18n/index.js';
import { formatNumber, t } from '../../i18n/index.js';
export function createCards({
vesselState,
@@ -161,7 +161,14 @@ export function createCards({
function formatSpeed(speed) {
return t('{speed}KT', {
speed: speed === null ? '--' : speed.toFixed(1),
speed:
speed === null
? '--'
: formatNumber(speed, {
minimumFractionDigits: 1,
maximumFractionDigits: 1,
useGrouping: false,
}),
});
}
+4 -2
View File
@@ -7,7 +7,7 @@ import {
GLOBAL_INFRARED_MAX_GAP_MS,
LIGHTNING_MAX_GAP_MS,
} from './clock.js';
import { t, msg } from '../../i18n/index.js';
import { formatUtcDayMonth, t, msg } from '../../i18n/index.js';
import { formatScaleLabel } from '../../ui/unitLabels.js';
const STOPS = [
@@ -31,7 +31,9 @@ const LIGHTNING_STOPS = [
['300+', '#00FF00'],
];
const utc = (value) =>
value ? `${value.slice(5, 16).replace('T', ' ')} UTC` : t('Unavailable');
value
? `${formatUtcDayMonth(value)} ${value.slice(11, 16)} UTC`
: t('Unavailable');
/** A per-application observation layer, using the existing layer lifecycle and
* row controls. History is transient: shared links always open latest imagery. */
+15 -1
View File
@@ -124,7 +124,21 @@ export function formatCockpitCoordinate(value, positive, negative) {
minimumFractionDigits: 3,
maximumFractionDigits: 3,
});
return `${amount}°${compassPointLabel(value >= 0 ? positive : negative)}`;
const code = value >= 0 ? positive : negative;
// Russian writes the hemisphere out ("30,203° с. ш."): a lone «С» after a
// degree sign reads as Celsius.
switch (code) {
case 'N':
return t('{value}°N', { value: amount });
case 'S':
return t('{value}°S', { value: amount });
case 'E':
return t('{value}°E', { value: amount });
case 'W':
return t('{value}°W', { value: amount });
default:
return `${amount}°${compassPointLabel(code)}`;
}
}
/**
+6 -1
View File
@@ -185,7 +185,12 @@ function sourceLabel(source) {
if (typeof source !== 'string') return source;
if (source === 'Local') return t('Local', { context: 'data source' });
const key = SOURCE_LABEL_KEYS.get(source);
return key ? t(key) : source;
if (key) return t(key);
// A layer with several providers joins their names ("Mapillary · Google
// Street View"); a name with a translation shows it.
return source.includes(' · ')
? source.split(' · ').map(translateKnown).join(' · ')
: translateKnown(source);
}
/**
+2 -2
View File
@@ -1,10 +1,10 @@
import { t } from '../i18n/index.js';
import { formatUtcDayMonth, t } from '../i18n/index.js';
const set = (node, key, value) => {
if (node[key] !== value) node[key] = value;
};
const utc = (tick) =>
Number.isFinite(Date.parse(tick))
? `${new Date(tick).toISOString().slice(5, 16).replace('T', ' ')} UTC`
? `${formatUtcDayMonth(tick)} ${new Date(tick).toISOString().slice(11, 16)} UTC`
: '';
/** Stable native transport with local preview and a coalesced 150 ms drag commit. */
+3
View File
@@ -652,6 +652,9 @@
html:not([lang='en']) .data-name {
overflow-wrap: break-word;
hyphens: auto;
/* No two-letter pieces such as "es-paciales": a word hyphenates only when
at least four letters stay on each side. */
hyphenate-limit-chars: 8 4 4;
}
.data-toggle-right {
+2 -2
View File
@@ -1,4 +1,4 @@
import { t } from '../i18n/index.js';
import { formatUtcDayMonth, t } from '../i18n/index.js';
import { createRailCards } from './railCards.js';
import { createRailTimeline } from './railTimeline.js';
@@ -15,7 +15,7 @@ const ORDER = [
const OBSERVED = new Set(ORDER.slice(2));
const utc = (time) =>
Number.isFinite(Date.parse(time))
? `${new Date(time).toISOString().slice(5, 16).replace('T', ' ')} UTC`
? `${formatUtcDayMonth(time)} ${new Date(time).toISOString().slice(11, 16)} UTC`
: t('Unavailable');
const age = (time) => {
const minutes = Math.max(