fix(i18n): second screenshot review: remaining English, numbers and wraps

From the re-shot Russian screenshots:
- Translated: weather frame/imagery status errors, HUD summary provenance
  ("НЕДОСТУПНО: СУДА AIS ОНЛАЙН"), Bhote Koshi map labels, cockpit signal
  distances (КМ). The HUD summary fields are separated with " · " in every
  language, so the style name and view band no longer read as one phrase.
- Numbers follow the locale: cockpit altitude ("26 175"), precipitation.
- No breaks inside codes and dates: ADS-B and similar in layer rows,
  Sentinel-2, cyclone issue dates (word joiner; the UI font has no U+2011),
  no-break space after label colons in cyclone details.
- Layout: count lines under ALPR, short unavailable chip (context
  "status chip"), roomier draw segments, tighter CCTV calibration chips,
  two-line beat titles and media card titles, wrapping weather status.
- Wording: ru advisory is «сводка» (was «бюллетень»; "Advisory center" is
  «Центр циклона по сводке»), Street View is «Просмотр улиц», OPACITY
  «НЕПРОЗР.», synced «синхр.», Area «Зона»; the import dialog no longer says
  "this scene" for several scenes. Glossary updated.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
German KhokhlovandClaude Opus 5.5 committed 2026-10-13 19:13:12 +04:00
1 parent 2b6ccad732
commit 54dce5b3bd
32 files changed
+1204 -346

No files matched your search

+8 -5
View File
@@ -11,7 +11,7 @@ import {
createWindInspectionMarker,
WIND_UNITS,
} from './inspection.js';
import { t } from '../../i18n/index.js';
import { t, msg } from '../../i18n/index.js';
import { unitLabel } from '../../ui/unitLabels.js';
/** Format a forecast timestamp explicitly in UTC. */
@@ -174,7 +174,7 @@ export function createWindLayer({
return true;
} catch (cause) {
if (controller.signal.aborted || request !== controller) return false;
error = cause?.message || 'Wind source unavailable';
error = cause?.message || msg('Wind source unavailable');
return true;
} finally {
signal?.removeEventListener('abort', abort);
@@ -260,8 +260,11 @@ export function createWindLayer({
requestedScalar() !== 'none' &&
manifest &&
(!manifest.scalar || manifest.scalar.kind !== overlay);
// Stored in English for diagnostics; shown translated.
const imageryError =
enabled && !loading ? diagnostic?.imageryError : null;
enabled && !loading && diagnostic?.imageryError
? t(diagnostic.imageryError)
: null;
const label = {
none: t('Wind motion'),
speed: t('Wind speed'),
@@ -303,7 +306,7 @@ export function createWindLayer({
? t('Loading forecast')
: preparing
? t('Preparing flow')
: error ||
: (error && t(error)) ||
manifest?.reason ||
imageryError ||
(scalarMissing ? t('Selected field unavailable') : null) ||
@@ -384,7 +387,7 @@ export function createWindLayer({
model: model === 'ifs' ? 'ECMWF IFS' : 'GFS',
field: label,
unit: unitLabel(legendUnit),
})}${historyStatus ? `\n${historyStatus}` : ''}\n${t('Valid: {time}', { time: valid || t('Unavailable') })}${loading ? ` · ${t('loading')}` : preparing ? ` · ${t('preparing')}` : ''}\n${t('Issued: {time}', { time: run || t('Unavailable') })}${manifest?.stale ? ' · STALE' : ''}${error ? '\n' + error : ''}${scalarMissing ? `\n${t('Selected field unavailable · wind remains visible')}` : ''}${imageryError && !scalarMissing ? `\n${t('{error} · wind remains visible', { error: imageryError })}` : ''}`,
})}${historyStatus ? `\n${historyStatus}` : ''}\n${t('Valid: {time}', { time: valid || t('Unavailable') })}${loading ? ` · ${t('loading')}` : preparing ? ` · ${t('preparing')}` : ''}\n${t('Issued: {time}', { time: run || t('Unavailable') })}${manifest?.stale ? ' · STALE' : ''}${error ? `\n${t(error)}` : ''}${scalarMissing ? `\n${t('Selected field unavailable · wind remains visible')}` : ''}${imageryError && !scalarMissing ? `\n${t('{error} · wind remains visible', { error: imageryError })}` : ''}`,
infoTitle: t(
'Surface wind at 10 m. Approximately 1° global grid. Curves follow the 10 m wind field, lifted 12 km for visibility; display height is not weather altitude. View lighting is for readability. Animation shows flow through one fixed forecast; it does not advance time. Color fields drape the globe basemap or the active photorealistic 3D Tiles.',
),
+4 -3
View File
@@ -5,6 +5,7 @@ import {
import { createWindRelief } from './relief.js';
import { orderWeatherImagery } from '../weather/imageryOrder.js';
import { NO_IMAGERY_HOST } from '../weather/imageryHost.js';
import { msg } from '../../i18n/index.js';
import { createWindGpuRendering } from './gpuRendering.js';
import { advectParticle, sampleWind } from './model.js';
import {
@@ -344,7 +345,7 @@ export function createWindRendering({
? !cesium.Primitive
: !collection || !cesium.SingleTileImageryProvider
) {
imageryError = 'Globe imagery unavailable';
imageryError = msg('Globe imagery unavailable');
return;
}
try {
@@ -384,12 +385,12 @@ export function createWindRendering({
imagery.alpha = overlay === 'temperature' ? 1 : 0.85;
if (gpuActive) updateImageryFade(viewer.scene.camera, true);
imageryErrorRemove = provider.errorEvent?.addEventListener(() => {
imageryError = 'Globe field image unavailable';
imageryError = msg('Globe field image unavailable');
});
viewer.scene?.requestRender?.();
} catch {
removeImagery();
imageryError = 'Globe field image unavailable';
imageryError = msg('Globe field image unavailable');
}
}