mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
refactor(i18n): key messages by English text; add Russian
Replace the semantic keys with the English source text, so code reads as the
UI does and English needs no catalog: t('Save keys'), tn(count, one, other)
for plurals, msg() for text stored in data, and bare data-i18n* markup that
translates the element's own English. Other languages are one flat JSON each.
- Simplify src/i18n: drop namespaces, the configurable locale pair
(GEV_DEFAULT_LOCALE / GEV_SECONDARY_LOCALE) and its build defines. Locale
comes from ?lang=, the stored choice, then browser languages.
- Add scripts/i18n.mjs (npm run i18n): extracts every message from t/tn/msg
and markup, and fails on missing, unused, placeholder-mismatched or
wrongly-shaped plural entries. npm test runs it via catalog.test.mjs.
- Add Russian (src/i18n/locales/ru.json, 833 messages), started from the
community catalog in #312 and reviewed against the current English.
- Fix data-i18n placed on parents that would wipe their children (cockpit
LEVEL and local weather cells, first-run EXPLORE MANUALLY tile), and a
doubled degree sign in the TRACK ACQUIRED signal.
- Rewrite docs/TRANSLATORS.md for the new workflow; drop sections the earlier
merge resurrected in docs/CURRENT-STATE.md.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
dfbaeafbd8
commit
13efd411b6
112 files changed
+4419
-4856
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import * as Cesium from 'cesium';
|
||||
import { t } from '../../i18n/index.js';
|
||||
import { t, msg } from '../../i18n/index.js';
|
||||
import {
|
||||
createCyberSonarSampler,
|
||||
isCyberContactSonarActive as isCyberSonarActive,
|
||||
@@ -120,10 +120,10 @@ export function createOverlays({ state: layerState, services, parts, source }) {
|
||||
const details = selected
|
||||
? [
|
||||
siteName
|
||||
? t('layers.missions.launchSiteValue', {
|
||||
? t('LAUNCH SITE · {site}', {
|
||||
site: shortMissionLabel(siteName, 20).toUpperCase(),
|
||||
})
|
||||
: t('layers.missions.launchSite'),
|
||||
: t('LAUNCH SITE'),
|
||||
]
|
||||
: [];
|
||||
return {
|
||||
@@ -589,38 +589,37 @@ export function createOverlays({ state: layerState, services, parts, source }) {
|
||||
const mission = shortMissionLabel(launch.name, 22).toUpperCase();
|
||||
const siteName = compactLaunchSiteName(launch.launchSite);
|
||||
const siteCallout = siteName
|
||||
? t('layers.missions.launchSiteValue', {
|
||||
? t('LAUNCH SITE · {site}', {
|
||||
site: shortMissionLabel(siteName, 20).toUpperCase(),
|
||||
})
|
||||
: t('layers.missions.launchSite');
|
||||
: t('LAUNCH SITE');
|
||||
let title = mission;
|
||||
let detail = siteCallout;
|
||||
if (mode === 'countdown') {
|
||||
title = t('layers.missions.replay.countdown', {
|
||||
title = t('T−{time} · {mission}', {
|
||||
time: String(state.countdownSeconds).padStart(2, '0'),
|
||||
mission,
|
||||
});
|
||||
detail = `${t('layers.missions.replay.standbyDetail')}\n${siteCallout}`;
|
||||
detail = `${t('LAUNCH STANDBY')}\n${siteCallout}`;
|
||||
} else if (mode === 'ascent') {
|
||||
title =
|
||||
state.elapsedSinceStart < 1
|
||||
? t('layers.missions.replay.liftoff', { mission })
|
||||
? t('LIFTOFF · {mission}', { mission })
|
||||
: t(
|
||||
launch.trajectory.length > 1
|
||||
? 'layers.missions.replay.ascentReplay'
|
||||
: 'layers.missions.replay.ascentEstimate',
|
||||
? msg('ASCENT REPLAY · {mission}')
|
||||
: msg('ASCENT ESTIMATE · {mission}'),
|
||||
{ mission },
|
||||
);
|
||||
detail = parts.policyHelpers.formatMissionEventTime(state.eventTime);
|
||||
} else if (mode === 'recovery') {
|
||||
title = t('layers.missions.replay.recovery', { mission });
|
||||
title = t('STAGE RE-ENTRY / RECOVERY · {mission}', { mission });
|
||||
detail = parts.policyHelpers.formatMissionEventTime(state.eventTime);
|
||||
} else if (mode === 'orbit') {
|
||||
title = t('layers.missions.replay.orbit', { mission });
|
||||
title = t('ORBIT REPLAY · {mission}', { mission });
|
||||
detail = parts.policyHelpers.formatMissionEventTime(state.eventTime);
|
||||
}
|
||||
if (layerState._replayPaused)
|
||||
title = t('layers.missions.replay.pausedPrefix', { title });
|
||||
if (layerState._replayPaused) title = t('PAUSED · {title}', { title });
|
||||
const nextText = `${title}\n${detail}`;
|
||||
if (nextText !== layerState._replayVehicleOverlayText) {
|
||||
layerState._replayVehicleOverlayText = nextText;
|
||||
|
||||
@@ -220,12 +220,12 @@ export function createPanel({ state: layerState, services, parts, source }) {
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' · ');
|
||||
return `<tr><td>${escapeMissionText(payload.name)}${payload.amount > 1 ? ` ×${payload.amount}` : ''}${detail ? `<small>${escapeMissionText(detail)}</small>` : ''}</td><td>${escapeMissionText(payload.type || t('layers.missions.rows.unspecified'))}</td><td>${escapeMissionText(payload.destination || launch.orbit?.name || t('layers.missions.rows.unavailable'))}</td></tr>`;
|
||||
return `<tr><td>${escapeMissionText(payload.name)}${payload.amount > 1 ? ` ×${payload.amount}` : ''}${detail ? `<small>${escapeMissionText(detail)}</small>` : ''}</td><td>${escapeMissionText(payload.type || t('UNSPECIFIED'))}</td><td>${escapeMissionText(payload.destination || launch.orbit?.name || t('UNAVAILABLE'))}</td></tr>`;
|
||||
})
|
||||
: [];
|
||||
if (launch.payloads.length > 5) {
|
||||
payloadRows.push(
|
||||
`<tr><td colspan="3" class="mission-table-empty">${t('layers.missions.rows.additionalPayloads', { count: launch.payloads.length - 5 })}</td></tr>`,
|
||||
`<tr><td colspan="3" class="mission-table-empty">${t('+{count} additional payload records', { count: launch.payloads.length - 5 })}</td></tr>`,
|
||||
);
|
||||
}
|
||||
layerState._missionPanel.querySelector(
|
||||
@@ -233,7 +233,7 @@ export function createPanel({ state: layerState, services, parts, source }) {
|
||||
).innerHTML = missionTableRows(
|
||||
payloadRows,
|
||||
3,
|
||||
t('layers.missions.rows.classified'),
|
||||
t('PAYLOAD DATA UNAVAILABLE'),
|
||||
);
|
||||
const stageRows = launch.recoveryStages.map((stage) => {
|
||||
const endpoint = stage.endpoint;
|
||||
@@ -241,21 +241,21 @@ export function createPanel({ state: layerState, services, parts, source }) {
|
||||
stage.destination ||
|
||||
(endpoint?.accuracy === 'PAD / RTLS'
|
||||
? launch.launchSite
|
||||
: t('layers.missions.rows.unavailable'));
|
||||
: t('UNAVAILABLE'));
|
||||
const position = endpoint
|
||||
? `${endpoint.lat.toFixed(2)}, ${endpoint.lon.toFixed(2)} · ${endpoint.accuracy}`
|
||||
: stage.downrangeKm > 0
|
||||
? t('layers.missions.rows.kmDownrange', {
|
||||
? t('{value} KM DOWNRANGE', {
|
||||
value: stage.downrangeKm.toLocaleString(),
|
||||
})
|
||||
: t('layers.missions.rows.positionUnavailable');
|
||||
: t('POSITION UNAVAILABLE');
|
||||
const stageDetail = [
|
||||
Number.isFinite(stage.flightNumber)
|
||||
? t('layers.missions.rows.flightNumber', {
|
||||
? t('FLIGHT {count}', {
|
||||
count: stage.flightNumber,
|
||||
})
|
||||
: null,
|
||||
stage.reused ? t('layers.missions.rows.reused') : null,
|
||||
stage.reused ? t('REUSED') : null,
|
||||
stage.recoveryType,
|
||||
]
|
||||
.filter(Boolean)
|
||||
@@ -263,7 +263,7 @@ export function createPanel({ state: layerState, services, parts, source }) {
|
||||
return `<tr><td>${escapeMissionText(stage.name)}${stageDetail ? `<small>${escapeMissionText(stageDetail)}</small>` : ''}</td><td>${escapeMissionText(stage.status)}</td><td>${escapeMissionText(destination)}<small>${escapeMissionText(position)}</small></td></tr>`;
|
||||
});
|
||||
layerState._missionPanel.querySelector('[data-mission-stages]').innerHTML =
|
||||
missionTableRows(stageRows, 3, t('layers.missions.rows.noStageData'));
|
||||
missionTableRows(stageRows, 3, t('NO STAGE RE-ENTRY / RECOVERY DATA'));
|
||||
const stageSection = layerState._missionPanel.querySelector(
|
||||
'[data-mission-stages-section]',
|
||||
);
|
||||
@@ -291,7 +291,7 @@ export function createPanel({ state: layerState, services, parts, source }) {
|
||||
'[data-mission-roster-count]',
|
||||
);
|
||||
if (count)
|
||||
count.textContent = t('layers.missions.roster.count', {
|
||||
count.textContent = t('{count} / 30D', {
|
||||
count: layerState._launches.length,
|
||||
});
|
||||
if (!list) return;
|
||||
@@ -301,7 +301,7 @@ export function createPanel({ state: layerState, services, parts, source }) {
|
||||
layerState._launches,
|
||||
);
|
||||
if (!entries.length) {
|
||||
list.innerHTML = `<div class="space-mission-roster-empty">${t('layers.missions.roster.empty')}</div>`;
|
||||
list.innerHTML = `<div class="space-mission-roster-empty">${t('NO MISSIONS AVAILABLE IN THE CURRENT 30-DAY WINDOW')}</div>`;
|
||||
restoreMissionRosterFocus(
|
||||
list,
|
||||
focusSnapshot,
|
||||
@@ -314,15 +314,12 @@ export function createPanel({ state: layerState, services, parts, source }) {
|
||||
list.innerHTML = entries
|
||||
.map(({ launch, index }) => {
|
||||
const color = parts.model.missionMarkerColor(launch).toCssColorString();
|
||||
const date =
|
||||
launch.launchTime?.slice(0, 10) ||
|
||||
t('layers.missions.roster.dateUnavailable');
|
||||
const provider =
|
||||
launch.provider || t('layers.missions.roster.unspecifiedOperator');
|
||||
const date = launch.launchTime?.slice(0, 10) || t('DATE UNAVAILABLE');
|
||||
const provider = launch.provider || t('UNSPECIFIED OPERATOR');
|
||||
const label = parts.overlays
|
||||
.shortMissionLabel(launch.name, 27)
|
||||
.toUpperCase();
|
||||
return `<button type="button" class="space-mission-roster-item" data-mission-roster-index="${index}" data-mission-roster-id="${escapeMissionText(launch.id)}" aria-label="${escapeMissionText(t('layers.missions.roster.selectAria', { mission: label }))}"><span class="space-mission-roster-marker" style="--mission-roster-color:${color}" aria-hidden="true"></span><span class="space-mission-roster-copy"><strong>${escapeMissionText(label)}</strong><small>${escapeMissionText(provider)} · ${escapeMissionText(date)}</small></span><span class="space-mission-roster-chevron" aria-hidden="true">›</span></button>`;
|
||||
return `<button type="button" class="space-mission-roster-item" data-mission-roster-index="${index}" data-mission-roster-id="${escapeMissionText(launch.id)}" aria-label="${escapeMissionText(t('Select {mission}', { mission: label }))}"><span class="space-mission-roster-marker" style="--mission-roster-color:${color}" aria-hidden="true"></span><span class="space-mission-roster-copy"><strong>${escapeMissionText(label)}</strong><small>${escapeMissionText(provider)} · ${escapeMissionText(date)}</small></span><span class="space-mission-roster-chevron" aria-hidden="true">›</span></button>`;
|
||||
})
|
||||
.join('');
|
||||
list.querySelectorAll('[data-mission-roster-index]').forEach((button) => {
|
||||
@@ -379,7 +376,7 @@ export function createPanel({ state: layerState, services, parts, source }) {
|
||||
setMissionPanelField(
|
||||
'[data-mission-distance]',
|
||||
Number.isFinite(altitudeM)
|
||||
? t('layers.missions.telemetry.km', {
|
||||
? t('{value} KM', {
|
||||
value: Math.max(0, altitudeM / 1000).toLocaleString(undefined, {
|
||||
maximumFractionDigits: 0,
|
||||
}),
|
||||
@@ -392,7 +389,7 @@ export function createPanel({ state: layerState, services, parts, source }) {
|
||||
setMissionPanelField(
|
||||
'[data-mission-speed]',
|
||||
Number.isFinite(speedMps)
|
||||
? t('layers.missions.telemetry.kmPerSecond', {
|
||||
? t('{value} KM/S', {
|
||||
value: (speedMps / 1000).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
@@ -473,16 +470,16 @@ export function createPanel({ state: layerState, services, parts, source }) {
|
||||
layerState._missionPanel.className = 'context-space-mission-detail';
|
||||
layerState._missionPanel.setAttribute(
|
||||
'aria-label',
|
||||
t('layers.missions.panel.selectedHeader'),
|
||||
t('SELECTED SPACE MISSION'),
|
||||
);
|
||||
layerState._missionPanel.innerHTML = `<div class="space-mission-view-header"><span>${t('layers.missions.panel.selectedHeader')}</span><button type="button" data-mission-close title="${t('layers.missions.panel.showAllTitle')}" aria-label="${t('layers.missions.panel.deselectAria')}">×</button></div><div class="space-mission-detail"><strong data-mission-title>${t('layers.missions.panel.mission')}</strong><span data-mission-field data-mission-provider></span><span data-mission-field>${t('layers.missions.panel.status')}<b data-mission-status></b></span><span data-mission-field>${t('layers.missions.panel.launchSite')}<b data-mission-site></b></span><span data-mission-field>${t('layers.missions.panel.launchTime')}<b data-mission-time></b></span><span data-mission-field>${t('layers.missions.panel.orbit')}<b data-mission-orbit></b></span><span>${t('layers.missions.panel.ascentPath')}<b data-mission-ascent-source></b></span><span data-mission-field>${t('layers.missions.panel.distance')}<b data-mission-distance></b></span><span data-mission-field>${t('layers.missions.panel.speed')}<b data-mission-speed></b></span></div><section class="mission-data-section"><h4>${t('layers.missions.panel.payload')}</h4><div class="mission-table-scroll"><table class="mission-data-table"><thead><tr><th>${t('layers.missions.panel.colName')}</th><th>${t('layers.missions.panel.colType')}</th><th>${t('layers.missions.panel.colDestination')}</th></tr></thead><tbody data-mission-payloads></tbody></table></div></section><section class="mission-data-section" data-mission-stages-section><h4>${t('layers.missions.panel.stagesSection')}</h4><div class="mission-table-scroll"><table class="mission-data-table"><thead><tr><th>${t('layers.missions.panel.colStage')}</th><th>${t('layers.missions.panel.colStatus')}</th><th>${t('layers.missions.panel.colFinalPosition')}</th></tr></thead><tbody data-mission-stages></tbody></table></div></section><div class="mission-replay-speed-control"><div class="mission-replay-speed-header"><label for="space-mission-replay-speed">${t('layers.missions.replay.speedLabel')}</label><output class="gev-slider-value" for="space-mission-replay-speed" data-mission-replay-speed-output>1×</output></div><input id="space-mission-replay-speed" class="gev-quantitative-slider" type="range" min="0.25" max="4" step="0.25" value="1" data-mission-replay-speed aria-label="${t('layers.missions.replay.speedAria')}"><div class="mission-replay-speed-scale" aria-hidden="true"><span>0.25×</span><span>1×</span><span>4×</span></div></div><div class="mission-action-row"><button type="button" class="mission-focus-button" data-mission-focus>${t('layers.missions.panel.focus')}</button><button type="button" class="mission-replay-button" data-mission-replay aria-pressed="false">${t('layers.missions.replay.start')}</button></div><div class="space-mission-nav"><button type="button" class="mission-nav-button" data-mission-prev title="${t('layers.missions.panel.prevTitle')}"><span aria-hidden="true">‹</span> ${t('layers.missions.panel.prev')}</button><span class="mission-nav-index" data-mission-index>—</span><button type="button" class="mission-nav-button" data-mission-next title="${t('layers.missions.panel.nextTitle')}">${t('layers.missions.panel.next')} <span aria-hidden="true">›</span></button></div><button type="button" class="panel-layer-toggle" data-mission-show-all>${t('layers.missions.panel.showAll')}</button>`;
|
||||
layerState._missionPanel.innerHTML = `<div class="space-mission-view-header"><span>${t('SELECTED SPACE MISSION')}</span><button type="button" data-mission-close title="${t('Show all missions')}" aria-label="${t('Deselect mission')}">×</button></div><div class="space-mission-detail"><strong data-mission-title>${t('MISSION')}</strong><span data-mission-field data-mission-provider></span><span data-mission-field>${t('STATUS · ')}<b data-mission-status></b></span><span data-mission-field>${t('LAUNCH SITE · ')}<b data-mission-site></b></span><span data-mission-field>${t('LAUNCH TIME · ')}<b data-mission-time></b></span><span data-mission-field>${t('ORBIT · ')}<b data-mission-orbit></b></span><span>${t('ASCENT PATH · ')}<b data-mission-ascent-source></b></span><span data-mission-field>${t('CURRENT DISTANCE FROM EARTH · ')}<b data-mission-distance></b></span><span data-mission-field>${t('SATELLITE SPEED · ')}<b data-mission-speed></b></span></div><section class="mission-data-section"><h4>${t('PAYLOAD')}</h4><div class="mission-table-scroll"><table class="mission-data-table"><thead><tr><th>${t('NAME')}</th><th>${t('TYPE')}</th><th>${t('DESTINATION')}</th></tr></thead><tbody data-mission-payloads></tbody></table></div></section><section class="mission-data-section" data-mission-stages-section><h4>${t('STAGE / RE-ENTRY / RECOVERY')}</h4><div class="mission-table-scroll"><table class="mission-data-table"><thead><tr><th>${t('STAGE')}</th><th>${t('STATUS')}</th><th>${t('FINAL POSITION')}</th></tr></thead><tbody data-mission-stages></tbody></table></div></section><div class="mission-replay-speed-control"><div class="mission-replay-speed-header"><label for="space-mission-replay-speed">${t('REPLAY SPEED')}</label><output class="gev-slider-value" for="space-mission-replay-speed" data-mission-replay-speed-output>1×</output></div><input id="space-mission-replay-speed" class="gev-quantitative-slider" type="range" min="0.25" max="4" step="0.25" value="1" data-mission-replay-speed aria-label="${t('Replay speed multiplier')}"><div class="mission-replay-speed-scale" aria-hidden="true"><span>0.25×</span><span>1×</span><span>4×</span></div></div><div class="mission-action-row"><button type="button" class="mission-focus-button" data-mission-focus>${t('FOCUS')}</button><button type="button" class="mission-replay-button" data-mission-replay aria-pressed="false">${t('REPLAY ASCENT')}</button></div><div class="space-mission-nav"><button type="button" class="mission-nav-button" data-mission-prev title="${t('Previous mission')}"><span aria-hidden="true">‹</span> ${t('PREV')}</button><span class="mission-nav-index" data-mission-index>—</span><button type="button" class="mission-nav-button" data-mission-next title="${t('Next mission')}">${t('NEXT')} <span aria-hidden="true">›</span></button></div><button type="button" class="panel-layer-toggle" data-mission-show-all>${t('SHOW ALL / DESELECT')}</button>`;
|
||||
layerState._missionPanel
|
||||
.querySelector('.mission-action-row')
|
||||
.insertAdjacentHTML(
|
||||
'beforeend',
|
||||
`<div class="mission-replay-transport" data-mission-replay-transport hidden>
|
||||
<button type="button" data-mission-replay-toggle title="${t('layers.missions.replay.pause')}" aria-label="${t('layers.missions.replay.pause')}">Ⅱ</button>
|
||||
<button type="button" class="cancel" data-mission-replay-cancel title="${t('layers.missions.replay.cancel')}" aria-label="${t('layers.missions.replay.cancel')}"><span aria-hidden="true">×</span></button>
|
||||
<button type="button" data-mission-replay-toggle title="${t('Pause replay')}" aria-label="${t('Pause replay')}">Ⅱ</button>
|
||||
<button type="button" class="cancel" data-mission-replay-cancel title="${t('Cancel replay')}" aria-label="${t('Cancel replay')}"><span aria-hidden="true">×</span></button>
|
||||
</div>`,
|
||||
);
|
||||
host.appendChild(layerState._missionPanel);
|
||||
|
||||
@@ -522,7 +522,7 @@ export function createPaths({ state: layerState, services, parts, source }) {
|
||||
return {
|
||||
lat: Cesium.Math.toDegrees(lat),
|
||||
lon: Cesium.Math.toDegrees(Cesium.Math.negativePiToPi(lon)),
|
||||
accuracy: t('layers.missions.estDownrange'),
|
||||
accuracy: t('EST. DOWNRANGE'),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -77,14 +77,14 @@ export function createPolicyHelpers({
|
||||
: 0;
|
||||
return {
|
||||
orbit: orbitName
|
||||
? `${orbitAllowed ? '' : t('layers.missions.rows.plannedPrefix')}${orbitName}`
|
||||
? `${orbitAllowed ? '' : t('PLANNED · ')}${orbitName}`
|
||||
: null,
|
||||
ascent:
|
||||
suppliedTrajectoryPoints > 1
|
||||
? t('layers.missions.rows.suppliedTrajectory')
|
||||
? t('SUPPLIED TRAJECTORY POINTS')
|
||||
: replayAvailable
|
||||
? t('layers.missions.rows.reconstructedEstimate')
|
||||
: t('layers.missions.rows.unavailable'),
|
||||
? t('RECONSTRUCTED ESTIMATE')
|
||||
: t('UNAVAILABLE'),
|
||||
replayAvailable: Boolean(replayAvailable),
|
||||
};
|
||||
}
|
||||
@@ -198,7 +198,7 @@ export function createPolicyHelpers({
|
||||
function formatMissionEventTime(launchTime) {
|
||||
const date = new Date(launchTime);
|
||||
if (!launchTime || !Number.isFinite(date.getTime()))
|
||||
return t('layers.missions.rows.unavailable');
|
||||
return t('UNAVAILABLE');
|
||||
return `${date.toISOString().slice(0, 10)}\n${date.toISOString().slice(11, 19)} UTC`;
|
||||
}
|
||||
|
||||
|
||||
@@ -201,10 +201,10 @@ export function createReplay({ state: layerState, services, parts, source }) {
|
||||
if (speedControl) speedControl.hidden = !replayAvailable;
|
||||
button.hidden = active || !replayAvailable;
|
||||
button.disabled = !replayAvailable;
|
||||
button.textContent = t('layers.missions.replay.start');
|
||||
button.textContent = t('REPLAY ASCENT');
|
||||
button.classList.remove('active');
|
||||
button.setAttribute('aria-pressed', String(active));
|
||||
button.title = t('layers.missions.replay.startTitle');
|
||||
button.title = t('Replay the estimated ascent with a following camera');
|
||||
if (transport) {
|
||||
transport.hidden = !active;
|
||||
transport.classList.toggle(
|
||||
@@ -219,13 +219,11 @@ export function createReplay({ state: layerState, services, parts, source }) {
|
||||
toggleButton.textContent = layerState._replayPaused ? '▶' : 'Ⅱ';
|
||||
toggleButton.setAttribute(
|
||||
'aria-label',
|
||||
layerState._replayPaused
|
||||
? t('layers.missions.replay.resume')
|
||||
: t('layers.missions.replay.pause'),
|
||||
layerState._replayPaused ? t('Resume replay') : t('Pause replay'),
|
||||
);
|
||||
toggleButton.title = layerState._replayPaused
|
||||
? t('layers.missions.replay.resume')
|
||||
: t('layers.missions.replay.pause');
|
||||
? t('Resume replay')
|
||||
: t('Pause replay');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,19 +234,19 @@ export function createReplay({ state: layerState, services, parts, source }) {
|
||||
);
|
||||
if (!transport || !layerState._replayCameraLaunchId) return;
|
||||
const phase = state.countdownActive
|
||||
? t('layers.missions.replay.phaseCountdown', {
|
||||
? t('T minus {seconds}', {
|
||||
seconds: state.countdownSeconds,
|
||||
})
|
||||
: state.preCountdownActive
|
||||
? t('layers.missions.replay.phasePreparing')
|
||||
? t('Preparing launch site')
|
||||
: state.elapsedSinceStart < 1
|
||||
? t('layers.missions.replay.phaseLiftoff')
|
||||
? t('Liftoff')
|
||||
: state.ascending
|
||||
? t('layers.missions.replay.phaseAscent')
|
||||
: t('layers.missions.replay.phaseOrbit');
|
||||
? t('Ascent replay')
|
||||
: t('Orbit replay');
|
||||
transport.setAttribute(
|
||||
'aria-label',
|
||||
`${phase}${layerState._replayPaused ? t('layers.missions.replay.pausedSuffix') : ''}`,
|
||||
`${phase}${layerState._replayPaused ? t(', paused') : ''}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user