fix: complete GhostMaps locale and voice integration with current main

This commit is contained in:
Mazeyar Moeini Feizabadi committed 2026-10-26 16:29:48 +01:00
1 parent 4da002bd42
commit 9496ee4d64
8 files changed
+39 -5

No files matched your search

+2
View File
@@ -10,3 +10,5 @@
- Release packed-image resources when a load is cancelled or fails, respect
injected or omitted GhostMaps sources, and wait for background cache warm-up
before removing provider test fixtures.
- Include Simplified Chinese translations and keep the combined voice prompt
within its existing size limit while retaining all spoken aliases.
+1
View File
@@ -5330,6 +5330,7 @@ request viewbox and continues searching without that geographic preference.
- The row reads `LIVE` while the stream is open. A five-minute catalog read is the backstop.
- **Files.** `/api/ghostmaps/file/{product}` serves only catalog products. Files are downloaded by commit-pinned raw URLs, so a CDN cannot return an older edition. They are cached on disk by blob sha, and blobs no current product uses are pruned. A request whose `?v=` names the current blob is `immutable`. Repository paths never reach the page.
- **Source ownership.** The application catalog receives `sources['s2-ghostmaps']` through the shared source contracts; an omitted or null source stays unavailable without opening a stream or fetching. The standalone source factory supplies the same-origin implementation and accepts replacements. Packed-image URLs are released on cancelled or failed product construction, and remain owned by a successfully loaded product until it is removed.
- **Voice and locales.** S2 can be toggled through its registered id and aliases. The model already sees the S2 GhostMaps brand in the id, and compact alias-hint separators keep the complete voice prompt within its existing 52,000-character limit; accepted aliases are unchanged. The row and reports are translated in Spanish, Russian and Simplified Chinese.
- **Rendering.** The page parses the KMZ with the import module's zip, KMZ and XML helpers into one `CustomDataSource` per product.
- Points become ground-clamped billboards with the depth test off, so they never sink into terrain or 3D tiles. Because the Google 3D map hides the globe, nothing else would stop far-side pins drawing through the planet. Pins are therefore horizon-culled with Street Level's `createHorizonCull` before their first frame and again whenever the camera moves.
- Lines and polygon outlines are ground-clamped polylines.
+1
View File
@@ -3880,6 +3880,7 @@
"src/i18n/locale.js",
"src/i18n/locales/es.json",
"src/i18n/locales/ru.json",
"src/i18n/locales/zh-CN.json",
"src/data/geoImportImages.js",
"src/data/geoImportPins.js",
"src/layers/streetLevel/tileMath.js",
+3 -2
View File
@@ -1054,10 +1054,11 @@ test('the voice TOOL SCHEMA matches the pinned contract — the mission mapping
// Radio markup and the complete production-request comparison pin locality.
// Restore the base camera/Globe View wording with the globe-rotation append.
// S2 GhostMaps adds its layer id to the generated layer enums.
assert.equal(block.length, 30946, 'serialized tool schema length drifted');
// Alias-hint separators omit spaces to keep the existing prompt budget.
assert.equal(block.length, 30888, 'serialized tool schema length drifted');
assert.equal(
crypto.createHash('sha256').update(block).digest('hex'),
'be53b22c55e620fb36c6ea0f276bfe5a59de47fa02ead99188ada40c0bf48cc0',
'b809253254b5589f3c199c218b405d8f661f040962fdd841f1182e5009119420',
'the first-run missions must ride EXISTING tools: no schema edit, no cache bust',
);
const instructions = fs.readFileSync(
+25 -1
View File
@@ -2818,5 +2818,29 @@
"Layers": "图层",
"Search": "搜索",
"More": "更多",
"Panels": "面板"
"Panels": "面板",
"S2 GhostMaps": "S2 GhostMaps",
"Intel Picture": "情报态势图",
"Kinetic 30d": "近 30 天军事行动",
"Border Crisis": "边境危机",
"Iran Picture": "伊朗态势图",
"Iran Kinetic": "伊朗军事行动",
"Yemen FLOT": "也门前线",
"Latest Drop": "最新发布",
"GhostMaps file could not be read": "无法读取 GhostMaps 文件",
"GhostMaps catalog unavailable": "GhostMaps 目录不可用",
"Malformed GhostMaps catalog": "GhostMaps 目录格式无效",
"{count} source links ↗ · click card to open the first": {
"other": "{count} 个来源链接 ↗ · 点击卡片打开第一个"
},
"S2 · {name}": "S2 · {name}",
"Report": "报告",
"Open the source for {title}": "打开 {title} 的来源",
"LIVE · GitHub {commit} · {message} · checked every {seconds}s": "实时 · GitHub {commit} · {message} · 每 {seconds} 秒检查一次",
"GitHub {commit} · {message} · reconnecting for live updates": "GitHub {commit} · {message} · 正在重新连接以获取实时更新",
"Connecting to the S2 GhostMaps repository…": "正在连接 S2 GhostMaps 仓库…",
"{count} placemarks": {
"other": "{count} 个地标"
},
"S2 Underground publishes these KMZ products to GitHub. New uploads are detected within seconds and replace the previous edition automatically. Click a marker for its report.": "S2 Underground 在 GitHub 发布这些 KMZ 产品。新上传的内容会在数秒内被检测到,并自动替换旧版本。点击标记查看报告。"
}
+2
View File
@@ -169,6 +169,8 @@
"NVG",
"REC",
"SRC {value}",
"S2 GhostMaps",
"S2 · {name}",
"Sentinel-2",
"Techno",
"Trance",
+2 -1
View File
@@ -43,7 +43,8 @@ test('the complete Realtime tool payload pins the manifest-generated layer relea
// reset guidance/defaults update only move_camera and mode descriptions.
// Restore base descriptions; append only globe-rotation defaults and fit guidance.
// S2 GhostMaps adds its layer id to the generated layer enums.
'1f95d78074559217872ccbdfa57d4363264ea88c1a22b259e6ebba3c8189b806',
// Compact alias separators preserve the existing prompt budget.
'0128b5e28a8baf0d6466bfdbc6e7a80fd4bb32d0d22ccadfade2af641714f12a',
);
});
+3 -1
View File
@@ -525,6 +525,8 @@ const SELF_EVIDENT_IDS = new Set([
'radio',
'wind',
'directions',
// The brand is already the layer id; all spoken aliases remain accepted.
's2-ghostmaps',
]);
/**
@@ -539,7 +541,7 @@ export function voiceLayerAliasHint() {
entry.toggle && entry.aliases.length && !SELF_EVIDENT_IDS.has(entry.id),
)
.map((entry) => `${entry.aliases.slice(0, 2).join('/')}→${entry.id}`)
.join('; ');
.join(';');
}
/** Field names that already carry their unit (altitudeM, speedKts, …). */