mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
Switch language in place, without a reload
Choosing a language in the picker now applies it at once. The choice is stored and ?lang is kept in step through replaceState, and the picker keeps focus. Code that writes translated text itself re-presents it on a switch: onLocaleChange() lets an owner listen, removed at teardown, and status writers hand over a function of the locale (voice cards, scene director, SDR, draw hints, imagery split, map sources, Bhote Koshi media) so the words are rebuilt rather than re-sent. The HUD, cockpit, radio, CCTV, launch, awareness and credit texts follow the same hook, and applyDocumentTranslations can be applied again without undoing text code wrote since. The unsaved-work registry and persistLocaleAndReload existed only to guard the reload, so they go, with their catalog entries.
This commit is contained in:
1 parent
ba20bc13d8
commit
b20c80e590
87 files changed
+1194
-777
No files matched your search
@@ -2,7 +2,12 @@ import {
|
||||
formatAwarenessLabel,
|
||||
AWARENESS_RADIUS_M,
|
||||
} from '../../data/militaryAwarenessEngine.js';
|
||||
import { formatNumber, t, translateKnown } from '../../i18n/index.js';
|
||||
import {
|
||||
formatNumber,
|
||||
onLocaleChange,
|
||||
t,
|
||||
translateKnown,
|
||||
} from '../../i18n/index.js';
|
||||
import { formatQuantity } from '../../ui/unitLabels.js';
|
||||
import { AWARENESS_PAGE_SIZE, AWARENESS_PAGE_ROTATE_MS } from './policy.js';
|
||||
|
||||
@@ -73,6 +78,12 @@ export function createPanel({ state: layerState, parts }) {
|
||||
/** The panel shows layer views from the first enable or result onwards. */
|
||||
function ensurePanel() {
|
||||
layerState.panelShown = true;
|
||||
// A shown view is worded again in a new locale.
|
||||
layerState.offPanelLocale ??= onLocaleChange(() => {
|
||||
const kind = layerState.panelView?.kind;
|
||||
if (kind === 'results') renderResults();
|
||||
else if (kind === 'standby') hidePanel();
|
||||
});
|
||||
}
|
||||
|
||||
function hidePanel() {
|
||||
@@ -92,6 +103,8 @@ export function createPanel({ state: layerState, parts }) {
|
||||
/** Clear the panel when the layer is destroyed. */
|
||||
function clearPanel() {
|
||||
if (layerState.panelShown) publish({ kind: 'empty' });
|
||||
layerState.offPanelLocale?.();
|
||||
layerState.offPanelLocale = null;
|
||||
layerState.panelShown = false;
|
||||
layerState.panelView = null;
|
||||
layerState.panelSignature = '';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as Cesium from 'cesium';
|
||||
import { t } from '../../i18n/index.js';
|
||||
import { onLocaleChange, t } from '../../i18n/index.js';
|
||||
import {
|
||||
MISSION_CLOSE_VIEW_RANGE_M,
|
||||
MISSION_GLOBE_VIEW_RANGE_M,
|
||||
@@ -436,12 +436,20 @@ export function createPanel({ state: layerState, services, parts, source }) {
|
||||
preview: scheduleMissionRosterPreview,
|
||||
clear: clearMissionRosterPreviewState,
|
||||
});
|
||||
// The roster and mission are worded again in a new locale.
|
||||
layerState._offMissionLocale = onLocaleChange(() => {
|
||||
renderMissionRoster();
|
||||
updateMissionTelemetry(true, false);
|
||||
publishPanel();
|
||||
});
|
||||
publishPanel();
|
||||
}
|
||||
|
||||
/** Stop presenting; the components return to their initial markup. */
|
||||
function clearMissionPanel() {
|
||||
layerState._missionPanelReady = false;
|
||||
layerState._offMissionLocale?.();
|
||||
layerState._offMissionLocale = null;
|
||||
layerState._missionRosterPreviewOwnership = null;
|
||||
layerState._missionRosterView = null;
|
||||
layerState._missionRosterSignature = null;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { getLocale } from '../../i18n/index.js';
|
||||
|
||||
export function createPresentation({
|
||||
state: layerState,
|
||||
services,
|
||||
@@ -10,9 +12,26 @@ export function createPresentation({
|
||||
return layerState._acceptedCatalogSnapshot;
|
||||
}
|
||||
|
||||
/** Build the station categories, labelled in the current locale. */
|
||||
|
||||
function buildCategories() {
|
||||
layerState._categories = Object.freeze(
|
||||
parts.categories
|
||||
.buildRadioCategories(layerState._stations)
|
||||
.map((category) => Object.freeze(category)),
|
||||
);
|
||||
layerState._categoriesLocale = getLocale();
|
||||
}
|
||||
|
||||
/** Return an immutable snapshot consumed by the right-rail UI. */
|
||||
|
||||
function getRadioUIState() {
|
||||
// Labels follow a language switch the next time the state is read.
|
||||
if (
|
||||
layerState._categories.length &&
|
||||
layerState._categoriesLocale !== getLocale()
|
||||
)
|
||||
buildCategories();
|
||||
const visible = parts.queries.visibleStations();
|
||||
const selected = parts.queries.selectedStation();
|
||||
return Object.freeze({
|
||||
@@ -98,6 +117,7 @@ export function createPresentation({
|
||||
return {
|
||||
getRadioAcceptedCatalogSnapshot,
|
||||
getRadioUIState,
|
||||
buildCategories,
|
||||
emitState,
|
||||
subscribeToRadio,
|
||||
subscribeToRadioPlaybackControls,
|
||||
|
||||
@@ -295,11 +295,7 @@ export function createRendering({
|
||||
layerState._stationById = new Map(
|
||||
stations.map((station) => [station.id, station]),
|
||||
);
|
||||
layerState._categories = Object.freeze(
|
||||
parts.categories
|
||||
.buildRadioCategories(stations)
|
||||
.map((category) => Object.freeze(category)),
|
||||
);
|
||||
parts.presentation.buildCategories();
|
||||
if (
|
||||
layerState._filter === DEFAULT_RADIO_FILTER &&
|
||||
!parts.categories.filterRadioStations(stations, DEFAULT_RADIO_FILTER)
|
||||
|
||||
@@ -38,6 +38,7 @@ export function createState({ services }) {
|
||||
layerState._stationById = new Map();
|
||||
|
||||
layerState._categories = [];
|
||||
layerState._categoriesLocale = null;
|
||||
|
||||
layerState._renderById = new Map();
|
||||
|
||||
|
||||
Reference in new issue
Block a user