Merge branch 'main' into fix/remove-operator-hud-layout

This commit is contained in:
Said Turksever authored and GitHub committed 2026-10-29 16:23:27 +00:00
commit c227f89852
22 files changed
+3262 -35

No files matched your search

+10
View File
@@ -5,6 +5,7 @@ import {
applyDocumentTranslations,
formatDate,
formatNumber,
formatRelativeTime,
msg,
persistLocaleAndReload,
setLocale,
@@ -47,6 +48,9 @@ test('normalizeLocale folds regional variants and rejects unshipped tags', () =>
assert.equal(normalizeLocale('xx'), null);
assert.equal(normalizeLocale('it-IT'), 'it');
assert.equal(normalizeLocale('it_CH'), 'it');
assert.equal(normalizeLocale('ja'), 'ja');
assert.equal(normalizeLocale('ja-JP'), 'ja');
assert.equal(normalizeLocale('JA_jp'), 'ja');
// Explicit script tags take precedence over regional defaults.
assert.equal(normalizeLocale('zh'), 'zh-CN');
assert.equal(normalizeLocale('zh-CN'), 'zh-CN');
@@ -214,7 +218,13 @@ test('Intl formatters follow the active locale', () => {
assert.equal(formatNumber(1234.5), '1,234.5');
setLocale('ru');
assert.equal(formatDate(date, options), '15 января 2026 г.');
assert.equal(formatRelativeTime(-5, 'minute'), '5 минут назад');
assert.equal(formatNumber(1234.5), '1 234,5');
// Japanese keeps a number and its unit together, as the catalog does.
setLocale('ja');
assert.equal(formatDate(date, options), '2026年1月15日');
assert.equal(formatRelativeTime(-5, 'minute'), '5分前');
assert.equal(formatRelativeTime(-3, 'day'), '3日前');
});
function fakeElement({ text = '', attributes = {} } = {}) {
+10 -2
View File
@@ -20,6 +20,7 @@ import de from './locales/de.json' with { type: 'json' };
import es from './locales/es.json' with { type: 'json' };
import fr from './locales/fr.json' with { type: 'json' };
import it from './locales/it.json' with { type: 'json' };
import ja from './locales/ja.json' with { type: 'json' };
import pt from './locales/pt.json' with { type: 'json' };
import ru from './locales/ru.json' with { type: 'json' };
import uk from './locales/uk.json' with { type: 'json' };
@@ -31,6 +32,7 @@ const CATALOGS = Object.freeze({
es,
fr,
it,
ja,
pt,
ru,
uk,
@@ -216,13 +218,19 @@ export function formatUtcDayMonth(value) {
/**
* Locale-aware relative time (Intl.RelativeTimeFormat), e.g.
* formatRelativeTime(-5, 'minute') → '5 minutes ago' / '5 минут назад'.
* formatRelativeTime(-5, 'minute') → '5 minutes ago' / '5 минут назад' /
* '5分前'.
*/
export function formatRelativeTime(value, unit = 'second', options) {
return cachedFormatter('relative', Intl.RelativeTimeFormat, {
const text = cachedFormatter('relative', Intl.RelativeTimeFormat, {
numeric: 'auto',
...options,
}).format(value, unit);
// CLDR spaces Japanese (5 分前); the ja catalog writes the number and its
// unit together (5分前), so the two must not differ on one screen.
return currentLocale === 'ja'
? text.replace(/(?<=\d) (?=\p{Script=Han})/gu, '')
: text;
}
/** Collapse markup whitespace so a message reads the same in HTML and JS. */
+21
View File
@@ -0,0 +1,21 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { setLocale } from './index.js';
import {
cockpitUnitCase,
formatCockpitDistance,
} from '../ui/cockpitPresentation.js';
test('Japanese cockpit distances keep the unit in its own case', () => {
try {
setLocale('ja');
assert.equal(formatCockpitDistance(14000), '14 km');
assert.equal(formatCockpitDistance(9500), '9.5 km');
assert.equal(cockpitUnitCase('km'), 'km');
setLocale('en');
assert.equal(formatCockpitDistance(14000), '14 KM');
assert.equal(cockpitUnitCase('km'), 'KM');
} finally {
setLocale('en');
}
});
+22
View File
@@ -0,0 +1,22 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { setLocale } from './index.js';
import { hudQuantity, LOCALIZED_LOCALITY } from '../hudLocalityFormat.js';
import { formatCockpitDistance } from '../ui/cockpitPresentation.js';
// revmain-opus-ja-i1-1: ja has no case, so HUD units keep the catalog case
// (km), as the cockpit already does and docs/translations/ja.md requires.
test('Japanese HUD units keep their case, like the cockpit', () => {
try {
setLocale('ja');
assert.equal(formatCockpitDistance(14000), '14 km');
assert.equal(hudQuantity(13, 'km'), '13 km');
assert.equal(hudQuantity(1.5, 'km', 1), '1.5 km');
assert.equal(
LOCALIZED_LOCALITY.near({ poi: 'Shibuya', city: 'Tokyo', distKm: 13 }),
'SHIBUYA(東京)付近 13 km',
);
} finally {
setLocale('en');
}
});
+3 -1
View File
@@ -14,6 +14,7 @@ export const LOCALES = Object.freeze([
'es',
'fr',
'it',
'ja',
'pt',
'ru',
'uk',
@@ -28,6 +29,7 @@ export const LOCALE_NAMES = Object.freeze({
es: 'Español',
fr: 'Français',
it: 'Italiano',
ja: '日本語',
pt: 'Português (Brasil)',
ru: 'Русский',
uk: 'Українська',
@@ -40,7 +42,7 @@ const RTL_LOCALES = Object.freeze([]);
/**
* Map any language tag to a shipped locale: 'ru-RU' and 'RU' → 'ru',
'de',
* 'de-AT' and 'de_CH' → 'de', 'ja-JP' → 'ja',
* 'pt-BR' and 'pt-PT' → 'pt' (Brazilian Portuguese),
* 'zh', 'zh-CN' and 'zh-Hans-SG' → 'zh-CN';
* 'zh-Hant', 'zh-TW', 'zh-HK' and 'zh-MO' → 'zh-Hant'.
File diff suppressed because it is too large. Load diff
+49
View File
@@ -638,6 +638,55 @@
"ΔN",
"▲ {frp} MW"
],
"ja": [
"1090 MHz",
"978 MHz UAT",
"AIS: --",
"AIS: {name}",
"BRG {value}°",
"BRG —",
"CAL {value}",
"CAL · {badge}",
"CCTV",
"CH {index} / {total}",
"CRS {value}°",
"CRT",
"FLIR",
"FLT",
"FM MHZ",
"FOV",
"FOV {value}°",
"FT",
"GEO",
"HDG",
"HDG {value}°",
"Ironbow",
"Landsat 8/9",
"MSG/S",
"NVG",
"POS: {time}Z",
"REC",
"S2 GhostMaps",
"SRC {value}",
"Sentinel-2",
"USB {rate} msg/s",
"WHOT/BHOT",
"dB",
"ft",
"hPa",
"km",
"km/h",
"kt",
"mph",
"{city} CCTV",
"{rate} msg/s",
"{source} HTTP {status}",
"{speed} kn",
"{type} SPD: {speed} HDG: {heading}",
"ΔE",
"ΔN",
"▲ {frp} MW"
],
"pt": [
"1090 MHz",
"978 MHz UAT",
+3
View File
@@ -17,6 +17,9 @@ test('Chinese HUD and cockpit units keep their case without spacing coordinates'
assert.equal(formatCockpitDistance(14000), '14\u00a0km');
assert.equal(LOCALIZED_LOCALITY.sector({ latDeg: 21.33, lonDeg: -77.5 }),
'扇区 21.33N 77.50W');
setLocale('ja');
assert.equal(hudQuantity(13, 'km'), '13 km');
assert.equal(hudQuantity(1.5, 'km', 1), '1.5 km');
setLocale('en');
assert.equal(hudQuantity(0, 'km'), '0KM');
assert.equal(hudQuantity(2069, 'km', 1), '2069.0KM');