i18n: fix review findings and polish ru/es strings

Fixes the 51 P0–P2 findings from the full review of the i18n branch and
the issues found while checking every new string on screen in ru and es.

- Translate errors and statuses that still reached ru/es in English:
  feed and tile errors, provider statuses, the ALPR chip, the traffic
  mode chip, voice plan step labels, fire feed values, receiver bands,
  scene save reasons and the Cesium attribution link.
- Show preset city names in the UI language (src/ui/placeNames.js);
  data and everything sent to the model stay English.
- Share layer names between the layer panel, HUD and voice card
  (src/ui/layerNames.js).
- Keep long ru/es strings whole: voice card error lines, analyst
  titles, the voice tier status, the Nepal evidence button, the ALPR
  retry chip. English layout is unchanged.
- Ask before a language switch drops unsaved work.
- Catalog fixes: glossary terms (пуск, пресет), gender agreement and
  consistent "peticiones" in es, fewer calques in both languages.
- Fix English text that was itself wrong (e.g. "Exit cockpit to fly to
  a weather", raw tool ids in voice plan steps).

Catalogs: es/ru 2535 messages each, complete.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
German KhokhlovandClaude Opus 5.5 committed 2026-10-15 23:49:52 +04:00
1 parent 8029747b7e
commit 00704ddc89
212 files changed
+9871 -909

No files matched your search

+49 -10
View File
@@ -1,9 +1,56 @@
import { LayerStateCoordinator } from '../data/layerStateCoordinator.js';
import { stampInitialShareGesture } from '../navigationPolicy.js';
import { canPresentDeferredStatusNotice } from '../loadingFeedback.js';
import { t } from '../i18n/index.js';
import { t, msg } from '../i18n/index.js';
import { UiLifetime } from './uiLifetime.js';
// One ready-made sentence per restore policy (SHARE_TRACKING_RESTORE_POLICIES
// label) and outcome: a label dropped into a template cannot take the case or
// article the sentence needs in every language. The generic template stays
// for a label this table does not know.
const SHARE_RESTORE_NOTICES = Object.freeze({
expired: Object.freeze({
flight: msg('Shared flight follow expired'),
'military flight': msg('Shared military flight follow expired'),
satellite: msg('Shared satellite follow expired'),
}),
'source-unavailable': Object.freeze({
flight: msg('Shared flight could not be restored — feed unavailable'),
'military flight': msg(
'Shared military flight could not be restored — feed unavailable',
),
satellite: msg('Shared satellite could not be restored — feed unavailable'),
}),
unavailable: Object.freeze({
flight: msg('Shared flight is unavailable'),
'military flight': msg('Shared military flight is unavailable'),
satellite: msg('Shared satellite is unavailable'),
}),
});
/**
* The status notice for a terminal share-tracking restore result.
* @param {{classification?: string, label?: string}} result
* @returns {string}
*/
export function shareTrackingRestoreNotice(result) {
const outcome =
result?.classification === 'expired' ||
result?.classification === 'source-unavailable'
? result.classification
: 'unavailable';
const ready = SHARE_RESTORE_NOTICES[outcome][result?.label];
if (ready) return t(ready);
const subject = result?.label ? t(result.label) : t('entity');
return outcome === 'expired'
? t('Shared {subject} follow expired', { subject })
: outcome === 'source-unavailable'
? t('Shared {subject} could not be restored — feed unavailable', {
subject,
})
: t('Shared {subject} is unavailable', { subject });
}
/** Own initial share restoration, durable layer state and restoration notices. */
export class ShareRestoration {
constructor({
@@ -219,15 +266,7 @@ export class ShareRestoration {
const noticeGeneration = ownsAcquiringNotice
? this._shareTrackingNoticeGeneration
: ++this._shareTrackingNoticeGeneration;
const subject = result.label ? t(result.label) : t('entity');
const message =
result.classification === 'expired'
? t('Shared {subject} follow expired', { subject })
: result.classification === 'source-unavailable'
? t('Shared {subject} could not be restored — feed unavailable', {
subject,
})
: t('Shared {subject} is unavailable', { subject });
const message = shareTrackingRestoreNotice(result);
const showAfterStartupCover = () => {
this._lifetime.frame(() => {
if (