i18n: fix the LGTM review findings and tidy the branch texts

- i18n scanner: lastError sink, no false sinks on defaults and ternaries
- shared src/i18n/marker.js for modules that only mark strings
- wind field messages move to wind/fields.js; CITY_POIS imports from cityPois.js
- drop review IDs, change history and stale references from comments and docs

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
German KhokhlovandClaude Opus 5.5 committed 2026-10-16 21:00:28 +04:00
1 parent 0ed05568f7
commit 20f4cf3763
178 files changed
+918 -948

No files matched your search

+28 -10
View File
@@ -4,9 +4,8 @@
// npm run i18n -- --prune also drop entries the code no longer uses
// npm run i18n -- --missing ru print what ru lacks, as JSON to translate
//
// A translation identical to the English is reported too, unless it is
// listed for that locale in src/i18n/same-as-english.json (codes, product
// names, words spelled the same in both languages).
// A translation left as the English fails unless src/i18n/same-as-english.json
// lists it.
//
// Messages are the English literals passed to t(), tn() and msg() in src/,
// plus the markup opted in with data-i18n* in src/ui/templates and index.html.
@@ -220,12 +219,30 @@ const JS_SINKS = [
// Also showToast?.(…) and this._showToast(…).
/\b_?(?:showToast|toast|setHint|announce|say)(?:\?\.)?\(\s*/g,
// `status` values are often codes ('ok', 'auth-failed'); visibleText drops
// those, so only readable text is reported.
/(?:^|[{,\s])(?:label|title|tooltip|placeholder|hint|ariaLabel|accessibilityLabel|caption|subtitle|kicker|emptyText|blurb|countLabel|status|loadingLabel|statusMessage)\s*:\s*/gm,
// Layer status set by assignment: this._error = …, stats.loadingLabel = ….
// A declared local (`const error = …`) is scratch, not a status field.
/(?<![\w$])(?<!\b(?:const|let|var)\s+)_?(?:error|loadingLabel|statusMessage|status)\s*(?:\?\?|\|\|)?=(?![=>])\s*/g,
// those, so only readable text is reported. A name right after `?` is a
// ternary branch (`ok ? status : 'Fallback'`), not a property.
/(?:^|[{,\s])(?<!\?\s*)(?:label|title|tooltip|placeholder|hint|ariaLabel|accessibilityLabel|caption|subtitle|kicker|emptyText|blurb|countLabel|status|loadingLabel|statusMessage)\s*:\s*/gm,
];
// Layer status set by assignment: this._error = …, stats.lastError = …,
// error = … (a layer factory keeps its status in `let error`). Not checked:
// the declaration itself (`const error = …`, `let status = …`) and a default
// value in a parameter list or destructuring (see defaultValue).
const ASSIGNMENT_SINK =
/(?<![\w$])(?<!\b(?:const|let|var)\s+)_?(?:error|lastError|loadingLabel|statusMessage|status)\s*(?:\?\?|\|\|)?=(?![=>])\s*/g;
JS_SINKS.push(ASSIGNMENT_SINK);
/**
* Whether `name = value` at `nameStart` is a default (`(status = 'idle') =>`,
* `const { error = '…' } = options`): it follows `(`, `[`, `{` or `,` and its
* value ends at `,` or a closing bracket. An assignment statement ends at `;`.
*/
function defaultValue(source, nameStart, valueStart) {
const before = source.slice(0, nameStart).trimEnd().at(-1);
if (!before || !'([{,'.includes(before)) return false;
const end = valueStart + expressionAt(source, valueStart).length;
const after = source.slice(end).trimStart()[0];
return Boolean(after) && ',)]}'.includes(after);
}
const MARKERS = /\b(?:t|tn|msg)\(/y;
/** The expression starting at `start`, up to its end at bracket depth 0. */
@@ -364,6 +381,8 @@ export function unmarkedScript(file, original) {
const start = match.index + match[0].length;
const line = lineAt(source, start);
if (ignored(line)) continue;
if (sink === ASSIGNMENT_SINK && defaultValue(source, match.index, start))
continue;
const html = /HTML/.test(match[0]);
for (const literal of valueLiterals(expressionAt(source, start))) {
const text = visibleText(literal, html);
@@ -377,8 +396,7 @@ export function unmarkedScript(file, original) {
/**
* UI text that is not marked for translation: markup without data-i18n* and
* string literals that reach the page without t(), tn() or msg().
* Opt out with translate="no" in markup or an `// i18n-ignore` comment on
* (or just above) the line in code.
* Opt-outs: see unmarkedMarkup; in code, `// i18n-ignore` on or above the line.
* @returns {{where: string, text: string}[]}
*/
export function findUnmarked() {
+70 -13
View File
@@ -53,7 +53,8 @@
"src/data/adsbLolFallback.js",
"src/data/aisStreamAdapter.js",
"src/data/aisWatchdog.js",
"src/sources/httpBody.js"
"src/sources/httpBody.js",
"src/i18n/marker.js"
],
"external": ["ws"]
},
@@ -79,6 +80,7 @@
"src/localRequestGate.mjs",
"src/data/routeSteps.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/rateLimit.js"
],
"external": []
@@ -97,7 +99,8 @@
"server/providers/space/launch-library.js",
"server/providers/common/http.js",
"src/data/spaceProviderRequests.js",
"src/sources/httpBody.js"
"src/sources/httpBody.js",
"src/i18n/marker.js"
],
"external": []
},
@@ -127,6 +130,7 @@
"server/providers/traffic.js",
"server/providers/common/http.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/data/tomtomTiles.js"
],
"external": []
@@ -148,6 +152,7 @@
"server/providers/firms.js",
"server/providers/common/http.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/data/firmsCsv.js"
],
"external": []
@@ -161,7 +166,8 @@
"server/providers/common/rate-limit.js",
"src/sources/rateLimit.js",
"src/data/gbfsSource.js",
"src/sources/httpBody.js"
"src/sources/httpBody.js",
"src/i18n/marker.js"
],
"external": []
},
@@ -192,7 +198,8 @@
"scripts/google-server-key.mjs",
"src/data/cctvFootprint.js",
"src/sources/cctvTypes.js",
"src/sources/httpBody.js"
"src/sources/httpBody.js",
"src/i18n/marker.js"
],
"external": []
},
@@ -210,7 +217,8 @@
"server/providers/common/rate-limit.js",
"src/sources/rateLimit.js",
"server/providers/common/http.js",
"src/sources/httpBody.js"
"src/sources/httpBody.js",
"src/i18n/marker.js"
],
"external": ["pbf"]
},
@@ -226,7 +234,8 @@
"src/data/radioCountry.js",
"server/providers/common/http.js",
"src/sources/radioBrowser.js",
"src/sources/httpBody.js"
"src/sources/httpBody.js",
"src/i18n/marker.js"
],
"external": []
},
@@ -248,6 +257,7 @@
"src/data/placeProviderPayloads.js",
"src/data/routeSteps.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/overpass.js",
"src/sources/rateLimit.js"
],
@@ -268,6 +278,7 @@
"server/providers/overpass/geometry.js",
"server/providers/overpass/transport.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/rateLimit.js"
],
"external": []
@@ -290,6 +301,7 @@
"src/data/regionalModel.js",
"src/nominatimGeocode.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/rateLimit.js",
"src/data/local_data/natural_earth/marine.json",
"src/data/local_data/natural_earth/regions.json",
@@ -303,6 +315,7 @@
"runtime": "node",
"exports": ["./server/providers/openai"],
"modules": [
"src/i18n/marker.js",
"src/hudLayoutPolicy.js",
"server/providers/common/rate-limit.js",
"server/providers/common/request.js",
@@ -335,6 +348,7 @@
"runtime": "node",
"exports": ["./server/standalone/key-setup"],
"modules": [
"src/i18n/marker.js",
"scripts/pinokio-environment.mjs",
"server/providers/common/source-root.js",
"server/standalone/key-setup.js",
@@ -367,6 +381,7 @@
"src/data/local_data/natural_earth/regions.json",
"src/data/local_data/natural_earth/marine.json",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/nominatim.js"
],
"external": []
@@ -435,6 +450,7 @@
"map-source-controls": {
"exports": ["./ui/maps"],
"modules": [
"src/i18n/marker.js",
"src/ui/mapSource.js",
"src/ui/mapSourceControls.js",
"src/mapStackChips.js",
@@ -450,6 +466,7 @@
"layer-panel": {
"exports": ["./ui/layers", "./ui/layers/feedback"],
"modules": [
"src/i18n/marker.js",
"src/ui/layers.js",
"src/ui/layerPanel.js",
"src/ui/layerNames.js",
@@ -528,6 +545,7 @@
"context-controls": {
"exports": ["./ui/context", "./ui/context/policy"],
"modules": [
"src/i18n/marker.js",
"src/ui/context.js",
"src/ui/contextActions.js",
"src/ui/contextBindings.js",
@@ -598,6 +616,7 @@
"ui-shell": {
"exports": ["./ui/shell"],
"modules": [
"src/i18n/marker.js",
"src/ui/placeNames.js",
"src/hudLayouts.js",
"src/hudLayoutPolicy.js",
@@ -794,6 +813,7 @@
"src/director/interactions/session.js",
"src/director/sharing/bundle.js",
"src/director/sharing/preview.js",
"src/i18n/marker.js",
"src/director/sharing/lifetime.js",
"src/director/authoring.js"
],
@@ -844,6 +864,7 @@
"src/data/inputOwnership.js",
"src/director/sharing/bundle.js",
"src/director/sharing/preview.js",
"src/i18n/marker.js",
"src/director/sharing/lifetime.js",
"src/director/authoring.js",
"src/scenes/sharing.js",
@@ -860,6 +881,7 @@
"live-observations": {
"exports": ["./sources/live"],
"modules": [
"src/i18n/marker.js",
"src/data/aircraftEmergency.js",
"src/sources/live/aircraft.js",
"src/sources/live/contract.js",
@@ -872,6 +894,7 @@
"civil-flights": {
"exports": ["./layers/flights"],
"modules": [
"src/i18n/marker.js",
"src/cyberSonar.js",
"src/data/aircraftClass.js",
"src/data/aircraftEmergency.js",
@@ -921,6 +944,7 @@
"military-flights": {
"exports": ["./layers/military"],
"modules": [
"src/i18n/marker.js",
"src/cyberSonar.js",
"src/data/aircraftClass.js",
"src/data/aircraftEmergency.js",
@@ -965,6 +989,7 @@
"aircraft-mechanics": {
"exports": ["./aircraft"],
"modules": [
"src/i18n/marker.js",
"src/data/aircraftClass.js",
"src/data/aircraftIcons.js",
"src/data/aircraftMeta.js",
@@ -1032,6 +1057,7 @@
"recent-imagery": {
"exports": ["./layers/recent-imagery"],
"modules": [
"src/i18n/marker.js",
"src/layers/recentImagery/index.js",
"src/layers/recentImagery/source.js",
"src/layers/recentImagery/model.js",
@@ -1159,6 +1185,7 @@
"src/data/tomtomTiles.js",
"src/sources/capability.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/openFreeMap.js",
"src/sources/militaryTileGeometry.js",
"src/sources/vectorTiles.js",
@@ -1181,6 +1208,7 @@
"awareness-layer": {
"exports": ["./layers/awareness"],
"modules": [
"src/i18n/marker.js",
"src/cyberSonar.js",
"src/cockpitMath.js",
"src/data/iconOrientation.js",
@@ -1244,6 +1272,7 @@
"src/sources/overpassRoads.js",
"src/sources/capability.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/openFreeMap.js",
"src/data/installationNames.js",
"src/sources/militaryTileGeometry.js",
@@ -1411,6 +1440,7 @@
"src/layers/alpr/tileRecords.js",
"src/sources/capability.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/vectorTiles.js",
"src/sources/phaseTiming.js",
"src/layers/alpr/floors.js",
@@ -1513,6 +1543,7 @@
"./maps/defaults"
],
"modules": [
"src/i18n/marker.js",
"src/maps/availability.js",
"src/maps/catalog.js",
"src/maps/controller.js",
@@ -2237,6 +2268,7 @@
"src/search/nominatim.js",
"src/nominatimGeocode.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/nominatim.js",
"src/app/layers/transit.js",
"src/data/transit.js",
@@ -2863,6 +2895,7 @@
"src/nominatimGeocode.js",
"src/data/regionalModel.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/nominatim.js",
"src/app/layers/transit.js",
"src/data/transitFeeds.js",
@@ -3012,9 +3045,7 @@
"src/layers/airQuality/model.js",
"src/layers/airQuality/source.js",
"src/ui/statusText.js",
"src/ui/layerNames.js",
"src/layers/wind/source.js",
"src/sources/windBody.js"
"src/ui/layerNames.js"
],
"external": [
"hls.js",
@@ -3074,6 +3105,7 @@
"src/nominatimGeocode.js",
"src/data/regionalModel.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/nominatim.js",
"src/sources/featureGeometry.js",
"src/sources/overpassFeaturesRecords.js",
@@ -3114,6 +3146,7 @@
"ui-share-restoration": {
"exports": ["./ui/share-restoration"],
"modules": [
"src/i18n/marker.js",
"src/data/installationFeedback.js",
"src/data/idSwitches.js",
"src/data/layerState.js",
@@ -3189,6 +3222,7 @@
"civil-flight-records": {
"exports": ["./layers/flights/records"],
"modules": [
"src/i18n/marker.js",
"src/layers/flights/records.js",
"src/layers/flights/recordPolicy.js",
"src/data/aircraftMeta.js",
@@ -3209,6 +3243,7 @@
"military-flight-records": {
"exports": ["./layers/military/records"],
"modules": [
"src/i18n/marker.js",
"src/layers/military/records.js",
"src/layers/military/recordPolicy.js",
"src/data/aircraftMeta.js",
@@ -3260,6 +3295,7 @@
"directions-layer": {
"exports": ["./layers/directions"],
"modules": [
"src/i18n/marker.js",
"src/layers/directions/index.js",
"src/data/pointerOwnerNames.js",
"src/layers/directions/source.js",
@@ -3335,6 +3371,7 @@
"src/data/tomtomTiles.js",
"src/layers/alpr/tileRecords.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/vectorTiles.js",
"src/sources/phaseTiming.js"
],
@@ -3372,6 +3409,7 @@
"src/data/tomtomTiles.js",
"src/sources/capability.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/openFreeMap.js",
"src/sources/militaryTileGeometry.js",
"src/sources/vectorTiles.js",
@@ -3409,6 +3447,7 @@
"src/layers/traffic/source.js",
"src/sources/overpassRoads.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/openFreeMap.js",
"src/data/installationNames.js",
"src/sources/militaryTileGeometry.js",
@@ -3426,6 +3465,7 @@
"src/layers/earthquakes/source.js",
"src/layers/earthquakes/records.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/layers/perimeters/source.js",
"src/layers/perimeters/records.js",
"src/layers/submarineCables/bundledSource.js",
@@ -3444,13 +3484,14 @@
"src/search/geospatial.js",
"src/data/regionalModel.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/nominatim.js"
],
"external": []
},
"source-http-body": {
"exports": ["./sources/http-body"],
"modules": ["src/sources/httpBody.js"],
"modules": ["src/sources/httpBody.js", "src/i18n/marker.js"],
"external": []
},
"overpass-lexer": {
@@ -3465,7 +3506,8 @@
"src/nominatimGeocode.js",
"src/search/geospatial.js",
"src/data/regionalModel.js",
"src/sources/httpBody.js"
"src/sources/httpBody.js",
"src/i18n/marker.js"
],
"external": []
},
@@ -3481,6 +3523,7 @@
"src/data/transitFeeds.js",
"src/data/transitProxy.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/transitHistory.js",
"src/sources/transitService.js",
"src/sources/transitHistoryStore.js",
@@ -3620,6 +3663,7 @@
"src/data/transitProxy.js",
"src/data/gtfsRealtime.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/sources/transitHistory.js",
"src/sources/transitService.js",
"src/sources/transitHistoryStore.js",
@@ -3643,6 +3687,7 @@
"modules": [
"src/layers/perimeters/index.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/layers/perimeters/source.js",
"src/layers/perimeters/records.js",
"src/layers/perimeters/cards.js",
@@ -3659,6 +3704,7 @@
"modules": [
"src/layers/gnss/index.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/layers/gnss/source.js",
"src/layers/gnss/records.js",
"src/i18n/index.js",
@@ -3672,7 +3718,11 @@
},
"gnss-source": {
"exports": ["./layers/gnss/source"],
"modules": ["src/sources/httpBody.js", "src/layers/gnss/source.js"],
"modules": [
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/layers/gnss/source.js"
],
"external": []
},
"perimeters-source": {
@@ -3680,6 +3730,7 @@
"modules": [
"src/layers/perimeters/records.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/layers/perimeters/source.js"
],
"external": []
@@ -3713,6 +3764,7 @@
"src/layers/wind/inspection.js",
"src/layers/wind/model.js",
"src/layers/wind/fields.js",
"src/i18n/marker.js",
"src/tools/queries/imagery.js",
"src/tools/queries/cables.js",
"src/tools/queries/surveillance.js",
@@ -3766,6 +3818,7 @@
"src/layers/cctv/sourcePolicy.js",
"src/layers/cyclones/source.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/layers/earthquakes/source.js",
"src/layers/earthquakes/records.js",
"src/layers/firms/source.js",
@@ -3812,6 +3865,8 @@
"src/layers/weather/source.js",
"src/layers/wind/source.js",
"src/sources/windBody.js",
"src/layers/wind/fields.js",
"src/layers/wind/model.js",
"src/layers/recentImagery/catalog.js",
"src/layers/recentImagery/model.js",
"src/layers/submarineCables/bundledSource.js",
@@ -3841,6 +3896,7 @@
"src/layers/airQuality/model.js",
"src/layers/airQuality/source.js",
"src/sources/httpBody.js",
"src/i18n/marker.js",
"src/i18n/index.js",
"src/i18n/locale.js",
"src/i18n/locales/es.json",
@@ -3855,7 +3911,8 @@
"modules": [
"src/layers/airQuality/model.js",
"src/layers/airQuality/source.js",
"src/sources/httpBody.js"
"src/sources/httpBody.js",
"src/i18n/marker.js"
],
"external": []
}
+4 -6
View File
@@ -3,12 +3,10 @@
* qa-scene-dialog-file-drop — the SHARE SCENE dialog's file control accepts a
* file dropped from the desktop, proved in a real browser.
*
* The dialog replaces the browser-drawn "Choose files / No file chosen" line
* with a translated one (src/ui/sceneSharing.js, fileChooser). The native
* input must stay the whole control underneath it: a shrunken 1 px input
* accepts drops only on its own pixel, so dragging a data-pack file onto the
* visible row selected nothing. This harness drops a file onto the centre of
* the visible row through CDP and expects `input.files` to hold it.
* The dialog draws a translated row over the native file input
* (src/ui/sceneSharing.js, fileChooser). The input must still cover the row,
* or drops miss it. Drops a file on the row's centre via CDP and expects
* `input.files` to hold it.
*
* Usage:
* node scripts/qa-scene-dialog-file-drop.mjs