mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 02:44:02 +00:00
i18n(ar): apply review round 2
Catalog: refresh/updates wording, received SDR aircraft, playing states, move-start button, impersonal layer note, live-data descriptions, arrival steps, retry timing, tracking spelling, military chip, dollar amounts, label: value statuses, upstream source, globe map, stage recovery, comparison signs as words, ellipses and earlier round-2 fixes. Code: FIRMS cell cards use the plural entry for their count (FIRES pruned), translated locator pin titles are isolated in RTL, legend stops keep their sign, voice timeout minutes agree with the number, CCTV badges are translated, first-run and referenced-item alignment. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
4f44a17b44
commit
8540535817
15 files changed
+253
-174
No files matched your search
+67
-55
@@ -8,7 +8,8 @@ Translation sources: abiyeenzo (#915).
|
||||
|
||||
- Modern Standard Arabic, neutral across regions. Address the user with plain imperatives: «انقر»، «فعّل»، «أعد المحاولة».
|
||||
- Arabic has no letter case: an UPPERCASE English HUD label becomes the same short Arabic label. Keep labels as short as the English: «مباشر»، «متقادم»، «متوقف».
|
||||
- Status words in progress use «جارٍ …» («جارٍ التحميل»); finished actions use the passive («تم الحفظ»، «أُلغي التحميل»).
|
||||
- Status words in progress use «جارٍ …» («جارٍ التحميل»، «… جارٍ تشغيل اللقطة»); finished actions use the passive («تم الحفظ»، «أُلغي التحميل»). Data that refreshes itself «يُحدَّث» (يتحدّث means "speaks"). A sentence about a `{placeholder}` whose gender and number vary stays impersonal: «{layers}: تم التفعيل للتو».
|
||||
- A label followed by its value takes a colon, so it does not read as a sentence: «الصوت: نشط»، «السياق: {value}».
|
||||
- Arabic punctuation in Arabic text: ، ؛ ؟ and «» for quotes. Keep `·` as the HUD separator, `—` with spaces, and `…`.
|
||||
- Arrows that show a sequence point the way Arabic reads: «الإشارات ← الأخبار ← المحلي», «{origin} ← {destination}».
|
||||
- Product names, provider names and codes stay in Latin letters: Google, Cesium ion, CelesTrak, NOAA, FIRMS, AIS, ADS-B, GNSS, CCTV, HUD, CRT, NVG, FLIR, WHOT/BHOT, Ironbow, Street View, Mapillary. Aviation and camera abbreviations stay Latin too: HDG, FOV, BRG, CRS, GS, TRK, V/S, SQUAWK. Local place names from the Bhote Koshi scene (Rasuwagadhi, Bidur, Timure…) stay Latin; well-known cities and countries are written in Arabic (أوستن، طوكيو، نيبال).
|
||||
@@ -21,10 +22,11 @@ Translation sources: abiyeenzo (#915).
|
||||
- Latin runs inside Arabic sentences (product names, codes, `{placeholders}` filled with English data) are isolated by the bidi algorithm; write them as plain text, without manual direction marks.
|
||||
- Position counters: a translated counter says «من» («القناة {index} من {total}», «الإطار {index} من {total}»); a spaced slash between two isolated numbers swaps them in right-to-left text. Counters the code builds from bare numbers (`01 / 25`, `1 / 3`) are shown left to right by `rtl.css`.
|
||||
- Code stays left to right: the JSON fields of the scene editor are LTR in every language.
|
||||
- Comparison signs `<` and `>` are mirrored glyphs in right-to-left text («< 2%» shows as «> 2%»). Write them as words: «أقل من 2%»، «أكثر من 10%»، «أقل من ساعة». A legend's open upper bound («300+», «-40») is isolated by `formatScaleLabel()`, so its sign stays where it is written.
|
||||
|
||||
## Units
|
||||
|
||||
Distances and speeds take Arabic abbreviations after the number, with a space: كم، م، كم/س، كم/ث، م/ث، ميل/س، عقدة (knots)، قدم (feet)، مم. Time: ث (seconds)، د (minutes)، س (hours)، يوم; compact age labels («3d», «5D AGO») use ي: «{count} ي»، «قبل {count} ي», since a plain string cannot make يوم agree with the count. Area: آكر (acres, the value is not converted; فدان is a different unit). Scientific and radio units stay Latin: MHz، dB، dBFS، dBZ، hPa، MW، MiB. `°` and `%` stay. Hemisphere letters in coordinates: ش (N)، ج (S)، ق (E)، غ (W), as in `21.33ش`.
|
||||
Distances and speeds take Arabic abbreviations after the number, with a space: كم، م، كم/س، كم/ث، م/ث، ميل/س، عقدة (knots)، قدم (feet)، مم. Time: ث (seconds)، د (minutes)، س (hours)، يوم; compact age labels («3d», «5D AGO») use ي: «{count} ي»، «قبل {count} ي», since a plain string cannot make يوم agree with the count. Area: آكر (acres, the value is not converted; فدان is a different unit). Money: the word دولار after the amount, not a bare `$`: «{amount} مليون دولار». Scientific and radio units stay Latin: MHz، dB، dBFS، dBZ، hPa، MW، MiB. `°` and `%` stay. Hemisphere letters in coordinates: ش (N)، ج (S)، ق (E)، غ (W), as in `21.33ش`.
|
||||
|
||||
## Plurals
|
||||
|
||||
@@ -39,59 +41,69 @@ Distances and speeds take Arabic abbreviations after the number, with a space:
|
||||
| `many` | 11–99, 111–199… | 11 مصدرًا |
|
||||
| `other` | 100–102, 200–202, fractions | 100 مصدر |
|
||||
|
||||
Every form must keep `{count}`. For one and two, Arabic names the quantity with the noun itself (مصدر واحد، مصدران), so the number follows in parentheses. `few` takes the plural noun; `many` the accusative singular (مصدرًا، مفتاحًا); `zero` and `other` the genitive singular. When a word next to the number cannot agree in every form, or a short chip has no room, put the number after a colon instead: «القريبة: {count}»، «الملفات المحددة: {count}».
|
||||
Every form must keep `{count}`. For one and two, Arabic names the quantity with the noun itself (مصدر واحد، مصدران), so the number follows in parentheses. `few` takes the plural noun; `many` the accusative singular (مصدرًا، مفتاحًا); `zero` and `other` the genitive singular. When a word next to the number cannot agree in every form, or a short chip has no room, put the number after a colon instead: «القريبة: {count}»، «الملفات المحددة: {count}». Where neither fits, «من أصل {total} من السجلات» agrees with any number. A standalone unit label («الدقائق») is never glued after a number: the voice-timeout options («3 دقائق»، «15 دقيقة») come from `Intl.NumberFormat` unit formatting, not from the catalog.
|
||||
|
||||
## Glossary
|
||||
|
||||
| English | العربية |
|
||||
| ----------------------------------------- | --------------------------------------------------------- |
|
||||
| layer / data layer | طبقة / طبقة بيانات |
|
||||
| feed / source | مصدر بيانات (short: مصدر) / مصدر |
|
||||
| LIVE (status) / live data | مباشر / البيانات المباشرة (not حي) |
|
||||
| SIMULATED | محاكى (status) / محاكاة |
|
||||
| stale / degraded / unavailable | متقادم / متدهور / غير متاح |
|
||||
| ON / OFF (state) | مفعّل / متوقف |
|
||||
| retry | إعادة المحاولة |
|
||||
| key (API key) / POWER UP | مفتاح (مفتاح API) / تشغيل |
|
||||
| Provider Settings | إعدادات المزوّدين |
|
||||
| globe / map / map source / basemap | الكرة الأرضية / الخريطة / مصدر الخريطة / الخريطة الأساسية |
|
||||
| tiles | بلاطات |
|
||||
| aircraft / flight / military flights | طائرة / رحلة / الرحلات العسكرية |
|
||||
| Live Flights / Live Vessels (layers) | تتبّع الرحلات / السفن المباشر (not الرحلات المباشرة) |
|
||||
| call sign | رمز النداء |
|
||||
| vessel, ship | سفينة |
|
||||
| satellite | قمر صناعي |
|
||||
| launch (rocket) / space mission | إطلاق / مهمة فضائية |
|
||||
| contact (tracked object) | هدف |
|
||||
| installation, site / mapped | منشأة، موقع / مرسوم |
|
||||
| camera / CCTV camera | كاميرا / كاميرا CCTV |
|
||||
| earthquake / active fire / fire perimeter | زلزال / حريق نشط / محيط حريق |
|
||||
| cyclone advisory | نشرة إعصار |
|
||||
| scene / shot / scene recipe | مشهد / لقطة / قالب المشهد |
|
||||
| briefing / panel / dock | إحاطة / لوحة / الشريط السفلي |
|
||||
| preset / visual preset | إعداد مسبق / نمط بصري |
|
||||
| Scope (circular viewport mask) / keyhole | المنظار / الفتحة |
|
||||
| Clean UI | واجهة نظيفة |
|
||||
| cockpit | القمرة (قمرة القيادة) |
|
||||
| heading / altitude / ground speed | الاتجاه (HDG) / الارتفاع / السرعة الأرضية |
|
||||
| Street Level / Street View | مستوى الشارع / Street View |
|
||||
| Recent Imagery | الصور الحديثة |
|
||||
| Global Context / Context | السياق العالمي / السياق |
|
||||
| radio station / tuner / gain | محطة / موالف / الكسب |
|
||||
| decoder (SDR) | مفكّك |
|
||||
| transit / bike share | النقل العام / الدراجات المشتركة |
|
||||
| Previous / Next | السابق / التالي |
|
||||
| compass points (N, NNE, …) | شمال، شمال شمال شرق، … |
|
||||
| forecast / valid (time) / issued | توقع / عند، وقت التوقع (not صالح حتى) / صدر |
|
||||
| observation / observed | رصد / مرصود |
|
||||
| field (weather) / model | حقل / نموذج |
|
||||
| parameters / ellipsoid | المعلمات / المجسّم الإهليلجي |
|
||||
| scene cloud | غيوم المشهد |
|
||||
| box (Recent Imagery area) / pin | منطقة / تثبيت |
|
||||
| THIS (voice pointer) | هذا |
|
||||
| outline / mark (map annotation) | مخطط / علامة، تعليم |
|
||||
| share (a view or link) | مشاركة |
|
||||
| AI agent | وكيل ذكاء اصطناعي |
|
||||
| stage (rocket) / downrange | مرحلة / على امتداد المسار |
|
||||
| frame (bring into view) | إظهار في الإطار |
|
||||
| story beat | مرحلة القصة |
|
||||
| English | العربية |
|
||||
| ------------------------------------------ | ---------------------------------------------------------- |
|
||||
| layer / data layer | طبقة / طبقة بيانات |
|
||||
| feed / source | مصدر بيانات (short: مصدر) / مصدر |
|
||||
| LIVE (status) / live data | مباشر / البيانات المباشرة (not حي) |
|
||||
| Live ships, live detections (descriptions) | بيانات مباشرة عن السفن، رصد مباشر (not the adverb مباشرةً) |
|
||||
| track, tracking | تتبّع (always with the shadda) |
|
||||
| SIMULATED | محاكى (status) / محاكاة |
|
||||
| stale / degraded / unavailable | متقادم / متدهور / غير متاح |
|
||||
| ON / OFF (state) | مفعّل / متوقف |
|
||||
| retry | إعادة المحاولة |
|
||||
| key (API key) / POWER UP | مفتاح (مفتاح API) / تشغيل |
|
||||
| Provider Settings | إعدادات المزوّدين |
|
||||
| globe / map / map source / basemap | الكرة الأرضية / الخريطة / مصدر الخريطة / الخريطة الأساسية |
|
||||
| globe map (map source drawn on the globe) | خريطة على الكرة الأرضية (not خريطة كروية) |
|
||||
| tiles | بلاطات |
|
||||
| aircraft / flight / military flights | طائرة / رحلة / الرحلات العسكرية |
|
||||
| Live Flights / Live Vessels (layers) | تتبّع الرحلات / السفن المباشر (not الرحلات المباشرة) |
|
||||
| call sign | رمز النداء |
|
||||
| vessel, ship | سفينة |
|
||||
| satellite | قمر صناعي |
|
||||
| launch (rocket) / space mission | إطلاق / مهمة فضائية |
|
||||
| contact (tracked object) | هدف |
|
||||
| installation, site / mapped | منشأة، موقع / مرسوم |
|
||||
| camera / CCTV camera | كاميرا / كاميرا CCTV |
|
||||
| earthquake / active fire / fire perimeter | زلزال / حريق نشط / محيط حريق |
|
||||
| cyclone advisory | نشرة إعصار |
|
||||
| scene / shot / scene recipe | مشهد / لقطة / قالب المشهد |
|
||||
| briefing / panel / dock | إحاطة / لوحة / الشريط السفلي |
|
||||
| preset / visual preset | إعداد مسبق / نمط بصري |
|
||||
| Scope (circular viewport mask) / keyhole | المنظار / الفتحة |
|
||||
| Clean UI | واجهة نظيفة |
|
||||
| cockpit | القمرة (قمرة القيادة) |
|
||||
| heading / altitude / ground speed | الاتجاه (HDG) / الارتفاع / السرعة الأرضية |
|
||||
| Street Level / Street View | مستوى الشارع / Street View |
|
||||
| Recent Imagery | الصور الحديثة |
|
||||
| Global Context / Context | السياق العالمي / السياق |
|
||||
| radio station / tuner / gain | محطة / موالف / الكسب |
|
||||
| decoder (SDR) | مفكّك |
|
||||
| transit / bike share | النقل العام / الدراجات المشتركة |
|
||||
| Previous / Next | السابق / التالي |
|
||||
| compass points (N, NNE, …) | شمال، شمال شمال شرق، … |
|
||||
| forecast / valid (time) / issued | توقع / عند، وقت التوقع (not صالح حتى) / صدر |
|
||||
| observation / observed | رصد / مرصود |
|
||||
| heard (aircraft received by the SDR) | الملتقطة |
|
||||
| upstream (camera feed) | المصدر الأصلي |
|
||||
| field (weather) / model | حقل / نموذج |
|
||||
| parameters / ellipsoid | المعلمات / المجسّم الإهليلجي |
|
||||
| scene cloud | غيوم المشهد |
|
||||
| box (Recent Imagery area) / pin | منطقة / تثبيت |
|
||||
| THIS (voice pointer) | هذا |
|
||||
| outline / mark (map annotation) | مخطط / علامة، تعليم |
|
||||
| share (a view or link) | مشاركة |
|
||||
| AI agent | وكيل ذكاء اصطناعي |
|
||||
| stage (rocket) / downrange | مرحلة / على امتداد المسار |
|
||||
| recovery (rocket stage) | استعادة (not استرجاع) |
|
||||
| Arrive at your destination (route step) | الوصول إلى وجهتك (a step, not وصلت) |
|
||||
| forecast lead hours | مدة التوقع بالساعات (not ساعات المهلة) |
|
||||
| cel-shaded | بتظليل كرتوني |
|
||||
| (debris-)dammed lake | بحيرة خلف سدّ (ركامي) |
|
||||
| frame (bring into view) | إظهار في الإطار |
|
||||
| story beat | مرحلة القصة |
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from './dataCredits.js';
|
||||
import { BHOTE_KOSHI_FLOOD_PATH } from './bhoteKoshiFloodPath.js';
|
||||
import { INCIDENT_OVERVIEW_PLACES } from './bhoteKoshiIncidentPlaces.js';
|
||||
import { t, msg, getLocale } from '../i18n/index.js';
|
||||
import { t, msg, getLocale, isolate } from '../i18n/index.js';
|
||||
|
||||
const BHOTE_KOSHI_LOCATOR_LAYER_ID = 'bhote-koshi-locator';
|
||||
export const BHOTE_KOSHI_LOCATOR_OVERLAY_SOURCE_ID =
|
||||
@@ -67,7 +67,10 @@ const PLACE_TITLE_TEXT = new Map(
|
||||
|
||||
function placeTitle(title) {
|
||||
const text = PLACE_TITLE_TEXT.get(title);
|
||||
return text ? t(text).toLocaleUpperCase(getLocale()) : title;
|
||||
// Isolated: the card draws left to right after its "11 · " counter, so in
|
||||
// Arabic a translated title with a Latin place name («نقطة الإطلالة في
|
||||
// DANDAGAUN») must keep its own right-to-left order.
|
||||
return text ? isolate(t(text).toLocaleUpperCase(getLocale())) : title;
|
||||
}
|
||||
|
||||
const INCIDENT = Object.freeze({
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
FIRMS_OVERLAY_SOURCE_ID,
|
||||
} from './firmsLabels.js';
|
||||
import { FIRE_ANCHOR_LIFT_M } from './fireAnchors.js';
|
||||
import { getLocale, setLocale } from '../i18n/index.js';
|
||||
import { reportMeshFloorCell, setMeshFloorPreferred } from './groundFloor.js';
|
||||
|
||||
const NOW = Date.UTC(2026, 6, 17, 4, 0);
|
||||
@@ -100,6 +101,30 @@ test('buildCellCard: plural noun, max FRP and newest age, accent passthrough', (
|
||||
assert.equal(card.accent, accentForSeverity('orange'));
|
||||
});
|
||||
|
||||
test('buildCellCard: the count picks the plural form of the language', () => {
|
||||
const title = (count) =>
|
||||
buildCellCard(
|
||||
{
|
||||
cell: { count, maxFrp: 10, newestAcqMs: 0 },
|
||||
position: { x: 0, y: 0, z: 0 },
|
||||
},
|
||||
NOW,
|
||||
).title;
|
||||
const previous = getLocale();
|
||||
try {
|
||||
assert.equal(title(1), '1 FIRE');
|
||||
setLocale('ar');
|
||||
assert.deepEqual(
|
||||
[2, 3, 14].map((count) => title(count).replace(/[\u2068\u2069]/g, '')),
|
||||
['حريقان (2)', '3 حرائق', '14 حريقًا'],
|
||||
);
|
||||
setLocale('ru');
|
||||
assert.equal(title(14), '14 ПОЖАРОВ');
|
||||
} finally {
|
||||
setLocale(previous);
|
||||
}
|
||||
});
|
||||
|
||||
// Owner field finding 2026-07-21: anchors must sit on the DEM once the shared
|
||||
// ground floor is warm — and the cached per-fire position must re-anchor when
|
||||
// the floor lands AFTER the first (cold, height-0) render. Distinct coords
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
import { hudQuantity, LOCALIZED_LOCALITY } from '../hudLocalityFormat.js';
|
||||
import { formatCockpitDistance } from '../ui/cockpitPresentation.js';
|
||||
import { READOUT_WORDS } from '../layers/recentImagery/display.js';
|
||||
import { formatQuantity } from '../ui/unitLabels.js';
|
||||
import { formatQuantity, formatScaleLabel } from '../ui/unitLabels.js';
|
||||
|
||||
test('Arabic resolves from URL, saved preference and browser language', () => {
|
||||
assert.equal(
|
||||
@@ -128,6 +128,22 @@ test('Arabic uses all six plural forms and spaced HUD units', () => {
|
||||
),
|
||||
'\u2068Austin\u2069 · \u2068HDG \u206868°\u2069\u2069 · \u2068FOV \u206844°\u2069\u2069',
|
||||
);
|
||||
// A legend's open bound keeps its plus on the written side: 300+.
|
||||
assert.deepEqual(['300+', '0.1'].map(formatScaleLabel), [
|
||||
'\u2068300+\u2069',
|
||||
'\u20680.1\u2069',
|
||||
]);
|
||||
// Counted minutes agree with the number (3–10 plural, 11+ singular).
|
||||
assert.deepEqual(
|
||||
[3, 15].map((n) =>
|
||||
formatNumber(n, {
|
||||
style: 'unit',
|
||||
unit: 'minute',
|
||||
unitDisplay: 'long',
|
||||
}),
|
||||
),
|
||||
['3 دقائق', '15 دقيقة'],
|
||||
);
|
||||
setLocale('ru');
|
||||
assert.equal(keepCodesWithValues('HDG 68°'), 'HDG 68°');
|
||||
assert.equal(formatCockpitDistance(14000), '14 КМ');
|
||||
|
||||
+88
-89
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"NO PLACE LEFT BEHIND": "لا مكان يُترك خلفنا",
|
||||
"Initializing photorealistic world...": "جارٍ تهيئة العالم الواقعي...",
|
||||
"Configuring viewer...": "جارٍ إعداد العارض...",
|
||||
"Google 3D Tiles unavailable ({detail}). Loading the keyless globe...": "بلاطات Google 3D Tiles غير متاحة ({detail}). جارٍ تحميل الكرة الأرضية بلا مفتاح...",
|
||||
"Flying to Austin, TX...": "جارٍ الانتقال إلى أوستن، تكساس...",
|
||||
"Restoring shared view...": "جارٍ استعادة العرض المشترك...",
|
||||
"Initializing photorealistic world...": "جارٍ تهيئة العالم الواقعي…",
|
||||
"Configuring viewer...": "جارٍ إعداد العارض…",
|
||||
"Google 3D Tiles unavailable ({detail}). Loading the keyless globe...": "بلاطات Google 3D Tiles غير متاحة ({detail}). جارٍ تحميل الكرة الأرضية بلا مفتاح…",
|
||||
"Flying to Austin, TX...": "جارٍ الانتقال إلى أوستن، تكساس…",
|
||||
"Restoring shared view...": "جارٍ استعادة العرض المشترك…",
|
||||
"LOADING LIVE DATA": "جارٍ تحميل البيانات المباشرة",
|
||||
"LOAD COMPLETE": "اكتمل التحميل",
|
||||
"LOAD FAILED": "فشل التحميل",
|
||||
"LOAD CANCELLED": "أُلغي التحميل",
|
||||
"syncing road network": "مزامنة شبكة الطرق",
|
||||
"syncing road network": "جارٍ مزامنة شبكة الطرق",
|
||||
"retrying in {seconds}s": "إعادة المحاولة خلال {seconds} ث",
|
||||
"retry pending": "إعادة المحاولة معلّقة",
|
||||
"Clear selected data layers": "مسح طبقات البيانات المحددة",
|
||||
@@ -22,9 +22,9 @@
|
||||
"Globe actions": "إجراءات الكرة الأرضية",
|
||||
"Reset camera and return to full globe view": "إعادة ضبط الكاميرا والعودة إلى عرض الكرة الأرضية كاملة",
|
||||
"loading frames": "جارٍ تحميل الإطارات",
|
||||
"Loading Google 3D Tiles...": "جارٍ تحميل بلاطات Google 3D Tiles...",
|
||||
"Loading the keyless globe...": "جارٍ تحميل الكرة الأرضية بلا مفتاح...",
|
||||
"Initializing systems...": "جارٍ تهيئة الأنظمة...",
|
||||
"Loading Google 3D Tiles...": "جارٍ تحميل بلاطات Google 3D Tiles…",
|
||||
"Loading the keyless globe...": "جارٍ تحميل الكرة الأرضية بلا مفتاح…",
|
||||
"Initializing systems...": "جارٍ تهيئة الأنظمة…",
|
||||
"LIVE DATA OFF": "البيانات المباشرة متوقفة",
|
||||
"MAPPED SITES LOADED": "تم تحميل المواقع المرسومة",
|
||||
"RETRYING MAPPED SITES": "جارٍ إعادة محاولة تحميل المواقع المرسومة",
|
||||
@@ -72,7 +72,7 @@
|
||||
"Working…": "جارٍ العمل…",
|
||||
"Could not open that mission{detail}. Retry or explore manually.": "تعذّر فتح تلك المهمة{detail}. أعد المحاولة أو استكشف يدويًا.",
|
||||
"This browser is blocking storage, so that could not be saved.": "هذا المتصفح يحظر التخزين، لذا تعذّر الحفظ.",
|
||||
"Live earthquakes and active fires, from USGS and NASA": "الزلازل والحرائق النشطة مباشرةً، من USGS وNASA",
|
||||
"Live earthquakes and active fires, from USGS and NASA": "بيانات مباشرة عن الزلازل والحرائق النشطة من USGS وNASA",
|
||||
"ENVIRONMENTAL": "البيئة",
|
||||
"EARTH WATCH": "مراقبة الأرض",
|
||||
"ACTIVE EVENTS": "الأحداث النشطة",
|
||||
@@ -106,7 +106,7 @@
|
||||
"ERROR": "خطأ",
|
||||
"Session ended — cost cap {cost}": "انتهت الجلسة — بلغت حد التكلفة {cost}",
|
||||
"VOICE STANDBY": "الصوت: استعداد",
|
||||
"VOICE ACTIVE": "الصوت نشط",
|
||||
"VOICE ACTIVE": "الصوت: نشط",
|
||||
"VOICE UNAVAILABLE": "الصوت غير متاح",
|
||||
"WebRTC microphone support unavailable": "دعم ميكروفون WebRTC غير متاح",
|
||||
"Requesting microphone": "جارٍ طلب الميكروفون",
|
||||
@@ -142,10 +142,10 @@
|
||||
"Could not exit {mode} — scene layers may be refused": "تعذّر الخروج من {mode} — قد تُرفض طبقات المشهد",
|
||||
"REMOVE": "إزالة",
|
||||
"Remove {title} from this app's saved keys": "إزالة {title} من مفاتيح هذا التطبيق المحفوظة",
|
||||
"Needs {envVars} — add it in Provider Settings": "يحتاج إلى {envVars} — أضفه في إعدادات المزوّدين",
|
||||
"Needs {envVars} — add it in Provider Settings": "يحتاج إلى {envVars} — أضفه في «إعدادات المزوّدين»",
|
||||
"Places context + Street View fallback; optional separate key": "سياق الأماكن + بديل Street View؛ مفتاح منفصل اختياري",
|
||||
"Live ships, worldwide": "السفن مباشرةً حول العالم",
|
||||
"Live active-fire detections": "رصد الحرائق النشطة مباشرة",
|
||||
"Live ships, worldwide": "بيانات مباشرة عن السفن حول العالم",
|
||||
"Live active-fire detections": "رصد مباشر للحرائق النشطة",
|
||||
"Real live traffic (keyless runs a simulation)": "حركة مرور مباشرة حقيقية (بدون مفتاح تُعرض محاكاة)",
|
||||
"Bing imagery map stacks + world terrain": "حزم خرائط صور Bing + تضاريس العالم",
|
||||
"More flight-polling credits (anonymous works without)": "رصيد أكبر لاستعلام الرحلات (يعمل دونه بصفة مجهولة)",
|
||||
@@ -179,7 +179,7 @@
|
||||
"NVG": "NVG",
|
||||
"Simulate FLIR-style thermal contrast. Turn up Ironbow for color.": "محاكاة تباين حراري بأسلوب FLIR. ارفع Ironbow لإظهار الألوان.",
|
||||
"FLIR": "FLIR",
|
||||
"Apply bright cel-shaded color and illustrated outlines.": "تطبيق ألوان زاهية مظلّلة بخطوط رسم توضيحية.",
|
||||
"Apply bright cel-shaded color and illustrated outlines.": "تطبيق ألوان زاهية بتظليل كرتوني وخطوط خارجية مرسومة.",
|
||||
"Anime": "أنمي",
|
||||
"Apply high-contrast monochrome film-noir grading.": "تطبيق تدرج أحادي اللون عالي التباين بأسلوب الفيلم نوار.",
|
||||
"Noir": "نوار",
|
||||
@@ -234,14 +234,14 @@
|
||||
"📍 Location: --": "📍 الموقع: --",
|
||||
"Landmark: --": "المَعلم: --",
|
||||
"Search any location": "البحث عن أي موقع",
|
||||
"Search any location...": "ابحث عن أي موقع...",
|
||||
"Search any location...": "ابحث عن أي موقع…",
|
||||
"LEVEL": "أفقي",
|
||||
"Estimated destination direction": "اتجاه الوجهة التقديري",
|
||||
"DEST ---°": "الوجهة ---°",
|
||||
"OPTICAL PLANE · 01": "المستوى البصري · 01",
|
||||
"VISOR LOCK · ACTIVE": "قفل واقي الخوذة · نشط",
|
||||
"FIRST PERSON": "منظور الشخص الأول",
|
||||
"LIVE TRACK · COURSE ALIGNED": "تتبع مباشر · المسار متوافق",
|
||||
"LIVE TRACK · COURSE ALIGNED": "تتبّع مباشر · بمحاذاة المسار",
|
||||
"Cockpit vision style": "نمط رؤية القمرة",
|
||||
"Current aircraft heading": "اتجاه الطائرة الحالي",
|
||||
"GROUND SPEED · KTS": "السرعة الأرضية · عقدة",
|
||||
@@ -347,11 +347,11 @@
|
||||
"Thermal": "حراري",
|
||||
"Current cockpit vision style: {style}. Activate for next style.": "نمط رؤية القمرة الحالي: {style}. فعّل للانتقال إلى النمط التالي.",
|
||||
"Current style: {style} — click for next": "النمط الحالي: {style} — انقر للتالي",
|
||||
"TRACK ACQUIRED": "تم التقاط المسار",
|
||||
"TRACK ACQUIRED": "تم التقاط الهدف",
|
||||
"{label} · COURSE {heading}°": "{label} · المسار {heading}°",
|
||||
"Select flight {title}": "اختيار الرحلة {title}",
|
||||
"CONTEXT STANDBY": "السياق في وضع الاستعداد",
|
||||
"ENABLE GLOBAL CONTEXT FOR PROXIMITY PINGS": "فعّل السياق العالمي لإشارات القرب",
|
||||
"ENABLE GLOBAL CONTEXT FOR PROXIMITY PINGS": "فعّل السياق العالمي لإشارات العناصر القريبة",
|
||||
"CONTACT LOST · {subject}": "فُقد الهدف · {subject}",
|
||||
"SUBJECT LEFT ITS FEED · READOUT HOLDING LAST KNOWN": "غادر الهدف مصدر بياناته · القراءة تحتفظ بآخر قيمة معروفة",
|
||||
"MILITARY FLIGHT": "رحلة عسكرية",
|
||||
@@ -371,11 +371,11 @@
|
||||
"AIRCRAFT": "طائرة",
|
||||
"MILITARY": "عسكرية",
|
||||
"COMMERCIAL": "تجارية",
|
||||
"ACQUIRING SURFACE": "جارٍ التقاط السطح",
|
||||
"ACQUIRING SURFACE": "جارٍ تحديد السطح",
|
||||
"SURFACE FALLBACK": "سطح بديل",
|
||||
"STALE FEED": "مصدر متقادم",
|
||||
"LIVE TRACK": "تتبع مباشر",
|
||||
"{aircraftClass} · {feedState} · COURSE ALIGNED": "{aircraftClass} · {feedState} · المسار متوافق",
|
||||
"LIVE TRACK": "تتبّع مباشر",
|
||||
"{aircraftClass} · {feedState} · COURSE ALIGNED": "{aircraftClass} · {feedState} · بمحاذاة المسار",
|
||||
"ARROW · ESTIMATED DIRECTION": "سهم · اتجاه تقديري",
|
||||
"DEST {bearing}": "الوجهة {bearing}",
|
||||
"CONTACT LOST · LAST KNOWN READOUT · NOT AN ALL-CLEAR": "فُقد الهدف · آخر قراءة معروفة · لا يعني أن الوضع آمن",
|
||||
@@ -437,8 +437,8 @@
|
||||
"Context": "السياق",
|
||||
"Space Missions": "المهام الفضائية",
|
||||
"{mode} could not start because another layer did not stop cleanly": "تعذّر بدء {mode} لأن طبقة أخرى لم تتوقف بشكل سليم",
|
||||
"Contacts could not complete the requested transition; try again": "تعذّر على الأهداف إكمال الانتقال المطلوب؛ أعد المحاولة",
|
||||
"Space Missions could not complete the requested transition; try again": "تعذّر على المهام الفضائية إكمال الانتقال المطلوب؛ أعد المحاولة",
|
||||
"Contacts could not complete the requested transition; try again": "تعذّر على وضع «الأهداف» إكمال الانتقال المطلوب؛ أعد المحاولة",
|
||||
"Space Missions could not complete the requested transition; try again": "تعذّر على وضع «المهام الفضائية» إكمال الانتقال المطلوب؛ أعد المحاولة",
|
||||
"Nearby installations could not be refreshed; try again": "تعذّر تحديث المنشآت القريبة؛ أعد المحاولة",
|
||||
"Context could not restore every layer; try again": "تعذّر على السياق استعادة كل الطبقات؛ أعد المحاولة",
|
||||
"Zoom in to search mapped installations": "قرّب الخريطة للبحث في المنشآت المرسومة",
|
||||
@@ -455,7 +455,7 @@
|
||||
"MAP": "خريطة",
|
||||
"CONTACTS — nearest planes · vessels · sites": "الأهداف — أقرب الطائرات · السفن · المواقع",
|
||||
"SPACE MISSIONS — launches & orbital assets": "المهام الفضائية — عمليات الإطلاق والأصول المدارية",
|
||||
"Space Missions cancellation could not restore the previous layer state": "تعذّر على إلغاء المهام الفضائية استعادة حالة الطبقة السابقة",
|
||||
"Space Missions cancellation could not restore the previous layer state": "تعذّرت استعادة حالة الطبقة السابقة عند إلغاء وضع المهام الفضائية",
|
||||
"Collapse Cockpit display options": "طي خيارات عرض القمرة",
|
||||
"Collapse Cockpit Radio controls": "طي عناصر تحكم الراديو في القمرة",
|
||||
"SYNC": "مزامنة",
|
||||
@@ -511,7 +511,7 @@
|
||||
"Resetting cockpit to full globe view": "جارٍ إعادة القمرة إلى عرض الكرة الأرضية كاملة",
|
||||
"ORBIT": "مدار",
|
||||
"SUMMARY": "الملخص",
|
||||
"Awaiting telemetry...": "بانتظار بيانات القياس عن بُعد...",
|
||||
"Awaiting telemetry...": "بانتظار بيانات القياس عن بُعد…",
|
||||
"REC": "REC",
|
||||
"Scope edge feather": "تنعيم حافة المنظار",
|
||||
"Bloom intensity": "شدة التوهج",
|
||||
@@ -541,7 +541,7 @@
|
||||
"Visible map targets": "أهداف الخريطة المرئية",
|
||||
"CCTV": "CCTV",
|
||||
"SOURCE · UNKNOWN": "المصدر · غير معروف",
|
||||
"Enable CCTV to load camera intersections": "فعّل CCTV لتحميل تقاطعات الكاميرات",
|
||||
"Enable CCTV to load camera intersections": "فعّل CCTV لتحميل كاميرات التقاطعات",
|
||||
"CCTV OFF": "CCTV متوقف",
|
||||
"NEAREST": "الأقرب",
|
||||
"CCTV camera": "كاميرا CCTV",
|
||||
@@ -611,10 +611,10 @@
|
||||
"{count}m ago": "قبل {count} د",
|
||||
"{count}h ago": "قبل {count} س",
|
||||
"never": "لم يُحدَّث",
|
||||
"loading...": "جارٍ التحميل...",
|
||||
"loading...": "جارٍ التحميل…",
|
||||
"UNCERTAIN · {source} · lifecycle state requires reconciliation": "غير مؤكد · {source} · حالة التشغيل تحتاج إلى تصحيح",
|
||||
"{state} · {source}": "{state} · {source}",
|
||||
"{state} · {source} · {detail} · retry {seconds}s": "{state} · {source} · {detail} · إعادة المحاولة {seconds} ث",
|
||||
"{state} · {source} · {detail} · retry {seconds}s": "{state} · {source} · {detail} · إعادة المحاولة خلال {seconds} ث",
|
||||
"{state} · {source} · {detail}": "{state} · {source} · {detail}",
|
||||
"{state} · {source} · {ago}": "{state} · {source} · {ago}",
|
||||
"{state} · {source} · {ago} · retrying in {seconds}s": "{state} · {source} · {ago} · إعادة المحاولة خلال {seconds} ث",
|
||||
@@ -672,7 +672,7 @@
|
||||
"VIEWSHED": "مجال الرؤية",
|
||||
"CAL {value}": "CAL {value}",
|
||||
"SRC {value}": "SRC {value}",
|
||||
"{value} CONTEXT": "السياق {value}",
|
||||
"{value} CONTEXT": "السياق: {value}",
|
||||
"News": "أخبار",
|
||||
"Talk": "حوارية",
|
||||
"Weather / Emergency": "الطقس / الطوارئ",
|
||||
@@ -721,7 +721,7 @@
|
||||
"Ready — playback starts only from your action": "جاهز — لا يبدأ التشغيل إلا بإجراء منك",
|
||||
"Connecting directly to broadcaster…": "جارٍ الاتصال مباشرة بالمحطة…",
|
||||
"Buffering broadcaster stream…": "جارٍ تخزين بث المحطة مؤقتًا…",
|
||||
"Playing {station}": "يجري تشغيل {station}",
|
||||
"Playing {station}": "جارٍ تشغيل {station}",
|
||||
"Paused {station}": "تم إيقاف {station} مؤقتًا",
|
||||
"Broadcaster stream unavailable": "بث المحطة غير متاح",
|
||||
" · degraded directory": " · دليل متدهور",
|
||||
@@ -753,7 +753,7 @@
|
||||
"NAME": "الاسم",
|
||||
"TYPE": "النوع",
|
||||
"DESTINATION": "الوجهة",
|
||||
"STAGE / RE-ENTRY / RECOVERY": "المراحل / العودة للغلاف الجوي / الاسترجاع",
|
||||
"STAGE / RE-ENTRY / RECOVERY": "المراحل / العودة للغلاف الجوي / الاستعادة",
|
||||
"STAGE": "المرحلة",
|
||||
"STATUS": "الحالة",
|
||||
"FINAL POSITION": "الموضع النهائي",
|
||||
@@ -767,13 +767,13 @@
|
||||
"Select {mission}": "اختيار {mission}",
|
||||
"+{count} additional payload records": "سجلات حمولة إضافية: +{count}",
|
||||
"PAYLOAD DATA UNAVAILABLE": "بيانات الحمولة غير متاحة",
|
||||
"NO STAGE RE-ENTRY / RECOVERY DATA": "لا توجد بيانات عن عودة المراحل للغلاف الجوي / استرجاعها",
|
||||
"NO STAGE RE-ENTRY / RECOVERY DATA": "لا توجد بيانات عن عودة المراحل للغلاف الجوي / استعادتها",
|
||||
"UNSPECIFIED": "غير محدد",
|
||||
"FLIGHT {count}": "الرحلة {count}",
|
||||
"REUSED": "أُعيد استخدامها",
|
||||
"{value} KM DOWNRANGE": "{value} كم على امتداد المسار",
|
||||
"PLANNED · ": "مخطط · ",
|
||||
"SUPPLIED TRAJECTORY POINTS": "نقاط مسار مزوَّدة",
|
||||
"SUPPLIED TRAJECTORY POINTS": "نقاط مسار من المصدر",
|
||||
"RECONSTRUCTED ESTIMATE": "تقدير مُعاد بناؤه",
|
||||
"{value} KM": "{value} كم",
|
||||
"{value} KM/S": "{value} كم/ث",
|
||||
@@ -789,7 +789,7 @@
|
||||
"LIFTOFF · {mission}": "الإقلاع · {mission}",
|
||||
"ASCENT REPLAY · {mission}": "إعادة عرض الصعود · {mission}",
|
||||
"ASCENT ESTIMATE · {mission}": "تقدير الصعود · {mission}",
|
||||
"STAGE RE-ENTRY / RECOVERY · {mission}": "عودة المراحل للغلاف الجوي / الاسترجاع · {mission}",
|
||||
"STAGE RE-ENTRY / RECOVERY · {mission}": "عودة المراحل للغلاف الجوي / الاستعادة · {mission}",
|
||||
"ORBIT REPLAY · {mission}": "إعادة عرض المدار · {mission}",
|
||||
"PAUSED · {title}": "متوقف مؤقتًا · {title}",
|
||||
"T minus {seconds}": "العد التنازلي: {seconds}",
|
||||
@@ -810,12 +810,12 @@
|
||||
"NAV": "ملاحة",
|
||||
"GNSS navigation — GPS, GLONASS, Galileo": "ملاحة GNSS — GPS وGLONASS وGalileo",
|
||||
"GEO": "GEO",
|
||||
"Geostationary belt — comms and weather, fixed over the equator": "الحزام الثابت بالنسبة للأرض — اتصالات وطقس، ثابتة فوق خط الاستواء",
|
||||
"Geostationary belt — comms and weather, fixed over the equator": "الحزام الثابت بالنسبة للأرض — أقمار اتصالات وطقس ثابتة فوق خط الاستواء",
|
||||
"VISUAL": "مرئية",
|
||||
"Brightest naked-eye objects — CelesTrak visual group": "ألمع الأجرام المرئية بالعين المجردة — مجموعة CelesTrak المرئية",
|
||||
"COMMS": "اتصالات",
|
||||
"Broadband constellation shell — shown only in DENSE mode": "غلاف كوكبة النطاق العريض — يظهر في وضع الكثيف فقط",
|
||||
"refreshing...": "جارٍ التحديث...",
|
||||
"refreshing...": "جارٍ التحديث…",
|
||||
"KEY REQUIRED": "المفتاح مطلوب",
|
||||
"STALE · cached {age}": "متقادم · مخزّن {age}",
|
||||
"LIVE · updated {age}": "مباشر · حُدّث {age}",
|
||||
@@ -823,27 +823,26 @@
|
||||
"FIRE · {frp} MW": "حريق · {frp} MW",
|
||||
"▲ {frp} MW": "▲ {frp} MW",
|
||||
"FIRE": "حريق",
|
||||
"FIRES": "حرائق",
|
||||
"{value} conf": "ثقة {value}",
|
||||
"{value} ago": "قبل {value}",
|
||||
"max {value} MW": "الأقصى {value} MW",
|
||||
"new {value}": "جديد {value}",
|
||||
"new {value}": "الأحدث قبل {value}",
|
||||
"NIGHT": "ليلًا",
|
||||
"sensor n/a": "المستشعر غير متاح",
|
||||
"Focus fire detection {title}, {details}": "التركيز على رصد الحريق {title}، {details}",
|
||||
"Syncing flow · Roads: OpenStreetMap · Flow: TomTom · Unmatched: simulated": "مزامنة التدفق · الطرق: OpenStreetMap · التدفق: TomTom · غير المطابق: محاكى",
|
||||
"Syncing flow · Roads: OpenStreetMap · Flow: TomTom · Unmatched: simulated": "جارٍ مزامنة التدفق · الطرق: OpenStreetMap · التدفق: TomTom · غير المطابق: محاكى",
|
||||
"LIVE · Roads: OpenStreetMap · Flow: TomTom · {percent}% cov": "مباشر · الطرق: OpenStreetMap · التدفق: TomTom · تغطية {percent}%",
|
||||
"LIVE · Roads: OpenStreetMap · Flow: TomTom · {percent}% cov · Unmatched: simulated": "مباشر · الطرق: OpenStreetMap · التدفق: TomTom · تغطية {percent}% · غير المطابق: محاكى",
|
||||
"SIMULATED · Roads: OpenStreetMap · Flow: TomTom (no matches)": "محاكى · الطرق: OpenStreetMap · التدفق: TomTom (لا تطابقات)",
|
||||
"Syncing flow · Roads: {source}": "مزامنة التدفق · الطرق: {source}",
|
||||
"Syncing flow · Roads: {source}": "جارٍ مزامنة التدفق · الطرق: {source}",
|
||||
"LIVE · Roads: {source} · Roads without flow hidden": "مباشر · الطرق: {source} · الطرق بلا بيانات تدفق مخفية",
|
||||
"LIVE · Roads: {source} · No flow roads in view": "مباشر · الطرق: {source} · لا طرق بها بيانات تدفق في نطاق العرض",
|
||||
"LIVE · Roads: {source} · Flow {percent}%": "مباشر · الطرق: {source} · التدفق {percent}%",
|
||||
"SIMULATED · Roads: {source} · Flow {percent}%": "محاكى · الطرق: {source} · التدفق {percent}%",
|
||||
"SIMULATED — traffic service unreachable": "محاكى — خدمة المرور غير متاحة",
|
||||
"SIMULATED — add TomTom key for live": "محاكى — أضف مفتاح TomTom للبيانات المباشرة",
|
||||
"syncing {count} city feeds...": "جارٍ مزامنة {count} من مصادر المدن...",
|
||||
"scanning nearby systems...": "جارٍ فحص الأنظمة القريبة...",
|
||||
"syncing {count} city feeds...": "جارٍ مزامنة {count} من مصادر المدن…",
|
||||
"scanning nearby systems...": "جارٍ فحص الأنظمة القريبة…",
|
||||
"🚲 {bikes} avail · {docks} docks · {capacity} cap": "🚲 المتاح {bikes} · المرابط {docks} · السعة {capacity}",
|
||||
"⚠️ Not installed": "⚠️ غير مثبتة",
|
||||
"⚠️ Not renting": "⚠️ لا تؤجّر",
|
||||
@@ -895,11 +894,11 @@
|
||||
"RAIN SHOWERS": "زخات مطر",
|
||||
"SNOW SHOWERS": "زخات ثلج",
|
||||
"THUNDERSTORM": "عاصفة رعدية",
|
||||
"MIXED CONDITIONS": "أحوال متفرقة",
|
||||
"MIXED CONDITIONS": "أحوال متباينة",
|
||||
"TAB PREVIEWS · ENTER / SPACE SELECTS": "TAB للمعاينة · ENTER / SPACE للاختيار",
|
||||
"awaiting usable AIS positions…": "بانتظار مواضع AIS صالحة…",
|
||||
"awaiting first AIS message…": "بانتظار أول رسالة AIS…",
|
||||
"EST. DOWNRANGE": "المسافة التقديرية على امتداد المسار",
|
||||
"EST. DOWNRANGE": "تقدير على امتداد المسار",
|
||||
"Pick a shape, then click the map.": "اختر شكلًا، ثم انقر على الخريطة.",
|
||||
"Enter to place the pin, Esc to cancel.": "Enter لوضع الدبوس، وEsc للإلغاء.",
|
||||
"Click where the pin goes.": "انقر حيث تريد وضع الدبوس.",
|
||||
@@ -951,10 +950,10 @@
|
||||
"REFERENCE ONLY · CLAIMS UNVERIFIED": "للمرجعية فقط · ادعاءات غير موثَّقة",
|
||||
"SOURCE GEOCONFIRMED": "موقع المصدر مؤكَّد جغرافيًا",
|
||||
"2021 historical reference versus 2026 post-event imagery; changes are cumulative and include the July 2025 Rasuwagadhi flood. Schematic downstream progression, not modeled arrival time; not an official hazard model.": "صورة مرجعية تاريخية من 2021 مقابل صور 2026 بعد الحدث؛ التغيرات تراكمية وتشمل فيضان Rasuwagadhi في يوليو 2025. تقدّم تخطيطي باتجاه المصب، لا زمن وصول منمذج؛ وليس نموذجًا رسميًا للمخاطر.",
|
||||
"Immediate collapse viewpoint": "نقطة مشاهدة الانهيار مباشرة",
|
||||
"Immediate collapse viewpoint": "نقطة مشاهدة الانهيار عن قرب",
|
||||
"Collapse viewpoint": "نقطة مشاهدة الانهيار",
|
||||
"Debris-dammed lake": "بحيرة سدّها الركام",
|
||||
"Dammed lake": "بحيرة مسدودة",
|
||||
"Debris-dammed lake": "بحيرة خلف سدّ ركامي",
|
||||
"Dammed lake": "بحيرة خلف سدّ",
|
||||
"Second landslide": "الانهيار الأرضي الثاني",
|
||||
"Gyirong border gate": "المعبر الحدودي في Gyirong",
|
||||
"Border gate": "المعبر الحدودي",
|
||||
@@ -1049,15 +1048,15 @@
|
||||
"■ RELEASE CAMERA": "■ تحرير الكاميرا",
|
||||
"Seek Nepal scene clock": "التنقل في توقيت مشهد نيبال",
|
||||
"NEPAL SCENE CLOCK": "توقيت مشهد نيبال",
|
||||
"… PLAYING SHOT": "… تشغيل اللقطة",
|
||||
"… PLAYING SHOT": "… جارٍ تشغيل اللقطة",
|
||||
"▶ PLAY SHOT": "▶ تشغيل اللقطة",
|
||||
"Ⅱ PAUSE": "Ⅱ إيقاف مؤقت",
|
||||
"↺ REPLAY CINEMATIC": "↺ إعادة العرض السينمائي",
|
||||
"↺ REPLAY": "↺ إعادة",
|
||||
"… PLAYING SCENE": "… تشغيل المشهد",
|
||||
"… PLAYING SCENE": "… جارٍ تشغيل المشهد",
|
||||
"Continue {scene} from next shot": "متابعة «{scene}» من اللقطة التالية",
|
||||
"current scene": "المشهد الحالي",
|
||||
"Replay the full reconstruction": "إعادة تشغيل إعادة البناء كاملة",
|
||||
"Replay the full reconstruction": "تشغيل إعادة البناء كاملة من البداية",
|
||||
"SCENE SHOT": "لقطة المشهد",
|
||||
"TIME UNVERIFIED": "الوقت غير موثَّق",
|
||||
"{count} SOURCES": {
|
||||
@@ -1337,9 +1336,9 @@
|
||||
"other": "{count} عاصفة نشطة"
|
||||
},
|
||||
"Position as of {time}": "الموضع عند {time}",
|
||||
"Maximum sustained wind: {wind} · Pressure: {pressure}": "أقصى رياح مستمرة: {wind} · الضغط: {pressure}",
|
||||
"Maximum sustained wind: {wind} · Pressure: {pressure}": "أقصى سرعة للرياح المستمرة: {wind} · الضغط: {pressure}",
|
||||
"{name} · {classification} · Advisory {number} · issued {time}": "{name} · {classification} · النشرة رقم {number} · صدرت {time}",
|
||||
"No active NHC/CPHC systems": "لا توجد أنظمة NHC/CPHC نشطة",
|
||||
"No active NHC/CPHC systems": "لا توجد أنظمة مدارية نشطة لدى NHC/CPHC",
|
||||
"Advisories unavailable": "النشرات غير متاحة",
|
||||
"Cyclones · NHC / CPHC": "الأعاصير · NHC / CPHC",
|
||||
"Atlantic · E/C Pacific": "الأطلسي · شرق/وسط الهادئ",
|
||||
@@ -1349,7 +1348,7 @@
|
||||
"Wind unavailable": "الرياح غير متاحة",
|
||||
"Advisory center / forecast track": "المركز حسب النشرة / المسار المتوقع",
|
||||
"Center-track uncertainty cone": "مخروط عدم اليقين لمسار المركز",
|
||||
"Select a storm on the map, or choose a storm in the list to select it and move the camera. Click empty map space to clear the selection. NOAA NHC/CPHC advisory context. The cone describes forecast center-track uncertainty, not storm size or the full hazard area. Forecast point labels are source lead hours, not times computed from advisory issuance. Geometry follows the surface; height is not weather altitude. Consult the official advisory.": "حدّد عاصفة على الخريطة، أو اخترها من القائمة لتحديدها وتحريك الكاميرا إليها. انقر على مساحة فارغة من الخريطة لإلغاء التحديد. سياق نشرات NOAA NHC/CPHC. يصف المخروط عدم اليقين في المسار المتوقع للمركز، لا حجم العاصفة ولا كامل منطقة الخطر. تسميات نقاط التوقع هي ساعات المهلة في المصدر، لا أوقات محسوبة من صدور النشرة. تتبع الأشكال الهندسية السطح؛ والارتفاع لا يمثل ارتفاع الظواهر الجوية. راجع النشرة الرسمية.",
|
||||
"Select a storm on the map, or choose a storm in the list to select it and move the camera. Click empty map space to clear the selection. NOAA NHC/CPHC advisory context. The cone describes forecast center-track uncertainty, not storm size or the full hazard area. Forecast point labels are source lead hours, not times computed from advisory issuance. Geometry follows the surface; height is not weather altitude. Consult the official advisory.": "حدّد عاصفة على الخريطة، أو اخترها من القائمة لتحديدها وتحريك الكاميرا إليها. انقر على مساحة فارغة من الخريطة لإلغاء التحديد. سياق نشرات NOAA NHC/CPHC. يصف المخروط عدم اليقين في المسار المتوقع للمركز، لا حجم العاصفة ولا كامل منطقة الخطر. تشير تسميات نقاط التوقع إلى مدة التوقع بالساعات كما يوردها المصدر، لا إلى أوقات محسوبة من وقت صدور النشرة. تتبع الأشكال الهندسية السطح؛ والارتفاع لا يمثل ارتفاع الظواهر الجوية. راجع النشرة الرسمية.",
|
||||
"DRIVE": "قيادة",
|
||||
"Drive": "بالسيارة",
|
||||
"WALK": "مشي",
|
||||
@@ -1383,8 +1382,8 @@
|
||||
"lane direction|right": "اليمنى",
|
||||
"lane direction|slightly left": "اليسرى",
|
||||
"lane direction|slightly right": "اليمنى",
|
||||
"lane direction|sharply left": "الأقصى يسارًا",
|
||||
"lane direction|sharply right": "الأقصى يمينًا",
|
||||
"lane direction|sharply left": "المخصّصة للانعطاف الحاد يسارًا",
|
||||
"lane direction|sharply right": "المخصّصة للانعطاف الحاد يمينًا",
|
||||
"lane direction|straight": "المستقيمة",
|
||||
"ordinal|{number}st": "رقم {number}",
|
||||
"ordinal|{number}nd": "رقم {number}",
|
||||
@@ -1392,9 +1391,9 @@
|
||||
"ordinal|{number}th": "رقم {number}",
|
||||
"Head out on {road}": "انطلق على {road}",
|
||||
"Head out": "انطلق",
|
||||
"Arrive at your destination, on the left": "وصلت إلى وجهتك، على اليسار",
|
||||
"Arrive at your destination, on the right": "وصلت إلى وجهتك، على اليمين",
|
||||
"Arrive at your destination": "وصلت إلى وجهتك",
|
||||
"Arrive at your destination, on the left": "الوصول إلى وجهتك، على اليسار",
|
||||
"Arrive at your destination, on the right": "الوصول إلى وجهتك، على اليمين",
|
||||
"Arrive at your destination": "الوصول إلى وجهتك",
|
||||
"Make a U-turn onto {road}": "استدر للخلف إلى {road}",
|
||||
"Make a U-turn": "استدر للخلف",
|
||||
"Continue straight onto {road}": "تابع إلى الأمام على {road}",
|
||||
@@ -1488,7 +1487,7 @@
|
||||
"fire confidence|high": "عالية",
|
||||
"fire confidence|nominal": "متوسطة",
|
||||
"fire confidence|low": "منخفضة",
|
||||
"age|<1h": "<1 س",
|
||||
"age|<1h": "أقل من ساعة",
|
||||
"age|{count}h": "{count} س",
|
||||
"age|{count}d": "{count} ي",
|
||||
"Source snapshot time unavailable": "وقت لقطة المصدر غير متاح",
|
||||
@@ -1526,14 +1525,14 @@
|
||||
},
|
||||
"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 منتجات KMZ هذه على GitHub. تُكتشف الملفات الجديدة خلال ثوانٍ وتحل محل الإصدار السابق تلقائيًا. انقر على علامة لعرض تقريرها.",
|
||||
"Malformed GhostMaps catalog": "فهرس GhostMaps مشوّه",
|
||||
"Low-accuracy score < 2%": "مؤشر ضعف الدقة < 2%",
|
||||
"Low-accuracy score < 2%": "مؤشر ضعف الدقة أقل من 2%",
|
||||
"Low-accuracy score 2–10%": "مؤشر ضعف الدقة 2–10%",
|
||||
"Low-accuracy score > 10%": "مؤشر ضعف الدقة > 10%",
|
||||
"Low-accuracy score > 10%": "مؤشر ضعف الدقة أكثر من 10%",
|
||||
"GNSS integrity source unavailable": "مصدر سلامة GNSS غير متاح",
|
||||
"Regional sample · 250 nm radius · cells from visited views over 30 min": "عيّنة إقليمية · نصف قطر 250 ميلًا بحريًا · خلايا من المناظر التي زرتها خلال 30 دقيقة",
|
||||
"Retrying automatically at {time} UTC": "إعادة المحاولة تلقائيًا عند {time} UTC",
|
||||
"Retrying automatically after provider cooldown": "إعادة المحاولة تلقائيًا بعد انتهاء مهلة المزوّد",
|
||||
"Updates automatically after pan or zoom and once a minute. The public feed covers a 250-nautical-mile circle around the view centre; zooming out does not make it a worldwide snapshot. Blank cells are outside sampled coverage or have insufficient observations.": "يتحدّث تلقائيًا بعد التحريك أو التكبير/التصغير ومرة كل دقيقة. يغطي المصدر العام دائرة نصف قطرها 250 ميلًا بحريًا حول مركز العرض؛ والتصغير لا يجعله لقطة عالمية. الخلايا الفارغة خارج نطاق العيّنة أو أرصادها غير كافية.",
|
||||
"Updates automatically after pan or zoom and once a minute. The public feed covers a 250-nautical-mile circle around the view centre; zooming out does not make it a worldwide snapshot. Blank cells are outside sampled coverage or have insufficient observations.": "يُحدَّث تلقائيًا بعد التحريك أو التكبير/التصغير ومرة كل دقيقة. يغطي المصدر العام دائرة نصف قطرها 250 ميلًا بحريًا حول مركز العرض؛ والتصغير لا يجعله لقطة عالمية. الخلايا الفارغة خارج نطاق العيّنة أو أرصادها غير كافية.",
|
||||
"Low-accuracy score = 100 × max(0, bad − 1) / total: one aircraft is discounted, so this is not the raw share. Cells need {aircraft} aircraft over {minutes} minutes. Navigation-integrity anomalies are not a detection of jamming or spoofing.": "مؤشر ضعف الدقة = 100 × max(0, الضعيفة − 1) / الإجمالي: تُستبعد طائرة واحدة، لذا فهو ليس النسبة الخام. تحتاج كل خلية إلى {aircraft} طائرات خلال {minutes} دقيقة. شذوذ سلامة الملاحة ليس كشفًا للتشويش أو الانتحال.",
|
||||
"GNSS snapshot needs a view anchor": "لقطة GNSS تحتاج إلى نقطة ارتكاز للعرض",
|
||||
"GNSS feed rate limited (HTTP 429)": "مصدر GNSS تجاوز حد الطلبات (HTTP 429)",
|
||||
@@ -1602,9 +1601,9 @@
|
||||
"receiver is in FM mode": "جهاز الاستقبال في وضع FM",
|
||||
"listening": "استماع",
|
||||
"USB error": "خطأ USB",
|
||||
"${amount}K": "{amount} ألف $",
|
||||
"${amount}M": "{amount} مليون $",
|
||||
"${amount}B": "{amount} مليار $",
|
||||
"${amount}K": "{amount} ألف دولار",
|
||||
"${amount}M": "{amount} مليون دولار",
|
||||
"${amount}B": "{amount} مليار دولار",
|
||||
"fire cause|Human": "بشري",
|
||||
"fire cause|Natural": "طبيعي",
|
||||
"fire cause|Undetermined": "غير محدد",
|
||||
@@ -1672,7 +1671,7 @@
|
||||
"{min}–{max}% scene cloud": "غيوم المشهد {min}–{max}%",
|
||||
"Comparison in use by another scene": "المقارنة مستخدمة في مشهد آخر",
|
||||
"Esri map unavailable · no swipe": "خريطة Esri غير متاحة · لا مقارنة بالسحب",
|
||||
"Swipe needs a globe map": "المقارنة بالسحب تتطلب خريطة كروية",
|
||||
"Swipe needs a globe map": "المقارنة بالسحب تتطلب خريطة على الكرة الأرضية",
|
||||
"Imagery stays on Esri · CLEAR to use Google 3D": "تبقى الصور على Esri · اضغط «مسح» لاستخدام Google 3D",
|
||||
"Imagery catalog unavailable": "فهرس الصور غير متاح",
|
||||
"Catalog truncated · a newer clear day may exist": "الفهرس مقتطع · قد يوجد يوم صافٍ أحدث",
|
||||
@@ -1697,7 +1696,7 @@
|
||||
"DOCKED · {name}": "ملتحم · {name}",
|
||||
"{name} needs the Google 3D map: choose it under MAP SOURCE": "يحتاج {name} إلى خريطة Google 3D: اخترها من «مصدر الخريطة»",
|
||||
"zoom in to a street to open {name}": "قرّب إلى شارع لفتح {name}",
|
||||
"loading coverage...": "جارٍ تحميل التغطية...",
|
||||
"loading coverage...": "جارٍ تحميل التغطية…",
|
||||
"No street-level imagery within {radius} m of that point": "لا توجد صور على مستوى الشارع ضمن {radius} م من تلك النقطة",
|
||||
"No street-level imagery within {radius} m of the view centre": "لا توجد صور على مستوى الشارع ضمن {radius} م من مركز العرض",
|
||||
"Zoom in to see street-level coverage": "قرّب لرؤية تغطية الصور على مستوى الشارع",
|
||||
@@ -1826,7 +1825,7 @@
|
||||
"feed down — retrying slowly": "المصدر متعطل — إعادة المحاولة على فترات أطول",
|
||||
"reconnecting to feed…": "جارٍ إعادة الاتصال بالمصدر…",
|
||||
"Focus vessel {name}, MMSI {mmsi}": "التركيز على السفينة {name}، MMSI {mmsi}",
|
||||
"Hidden by this map source · choose a globe map": "مخفي بسبب مصدر الخريطة هذا · اختر خريطة كروية",
|
||||
"Hidden by this map source · choose a globe map": "مخفي بسبب مصدر الخريطة هذا · اختر خريطة على الكرة الأرضية",
|
||||
"Weather image HTTP {status}": "صورة الطقس: HTTP {status}",
|
||||
"Weather HTTP {status}": "الطقس: HTTP {status}",
|
||||
"Frame unavailable; previous observation retained": "الإطار غير متاح؛ أُبقي على الرصد السابق",
|
||||
@@ -2052,7 +2051,7 @@
|
||||
"Bhote Koshi Corridor Overview": "نظرة عامة على ممر Bhote Koshi",
|
||||
"Bhote Koshi Upper Valley": "الوادي العلوي لـ Bhote Koshi",
|
||||
"Upper Valley Collapse": "انهيار الوادي العلوي",
|
||||
"Debris-Dammed Lake": "بحيرة سدّها الركام",
|
||||
"Debris-Dammed Lake": "بحيرة خلف سدّ ركامي",
|
||||
"Nepal-China Border Gate": "المعبر الحدودي بين نيبال والصين",
|
||||
"Timure Evidence Cluster": "مجموعة أدلة Timure",
|
||||
"Syabru Besi Passage": "العبور عند Syabru Besi",
|
||||
@@ -2107,7 +2106,7 @@
|
||||
"New anchor ID": "معرّف نقطة الارتكاز الجديدة",
|
||||
"Capture camera as anchor": "حفظ الكاميرا كنقطة ارتكاز",
|
||||
"Anchor added to draft": "أُضيفت نقطة الارتكاز إلى المسودة",
|
||||
"Set move start to current camera": "تعيين بداية الحركة إلى الكاميرا الحالية",
|
||||
"Set move start to current camera": "تعيين وضع الكاميرا الحالي بدايةً للحركة",
|
||||
"Move added to draft; destination remains the shot camera": "أُضيفت الحركة إلى المسودة؛ تبقى كاميرا اللقطة هي الوجهة",
|
||||
"Use ordinary flight": "استخدام انتقال عادي",
|
||||
"Invalid shot JSON": "JSON اللقطة غير صالح",
|
||||
@@ -2189,7 +2188,7 @@
|
||||
"{value}m": "{value} م",
|
||||
"SNAPSHOT": "لقطة",
|
||||
"LIVE": "مباشر",
|
||||
"UPSTREAM": "المصدر",
|
||||
"UPSTREAM": "المصدر الأصلي",
|
||||
"SYNTHETIC": "محاكاة",
|
||||
"CONFIGURED": "مُعَدّ",
|
||||
"SEED": "الفهرس",
|
||||
@@ -2328,12 +2327,12 @@
|
||||
"audio signal --": "إشارة الصوت --",
|
||||
"audio {state}": "الصوت: {state}",
|
||||
"{count} HEARD": {
|
||||
"zero": "المسموعة: {count}",
|
||||
"one": "المسموعة: {count}",
|
||||
"two": "المسموعة: {count}",
|
||||
"few": "المسموعة: {count}",
|
||||
"many": "المسموعة: {count}",
|
||||
"other": "المسموعة: {count}"
|
||||
"zero": "الملتقطة: {count}",
|
||||
"one": "الملتقطة: {count}",
|
||||
"two": "الملتقطة: {count}",
|
||||
"few": "الملتقطة: {count}",
|
||||
"many": "الملتقطة: {count}",
|
||||
"other": "الملتقطة: {count}"
|
||||
},
|
||||
"DISCONNECT": "قطع الاتصال",
|
||||
"CONNECT": "اتصال",
|
||||
@@ -2577,12 +2576,12 @@
|
||||
},
|
||||
"Loading {feeds}": "جارٍ تحميل {feeds}",
|
||||
"{count} heard": {
|
||||
"zero": "المسموعة: {count}",
|
||||
"one": "المسموعة: {count}",
|
||||
"two": "المسموعة: {count}",
|
||||
"few": "المسموعة: {count}",
|
||||
"many": "المسموعة: {count}",
|
||||
"other": "المسموعة: {count}"
|
||||
"zero": "الملتقطة: {count}",
|
||||
"one": "الملتقطة: {count}",
|
||||
"two": "الملتقطة: {count}",
|
||||
"few": "الملتقطة: {count}",
|
||||
"many": "الملتقطة: {count}",
|
||||
"other": "الملتقطة: {count}"
|
||||
},
|
||||
"USB {rate} msg/s": "USB {rate} رسالة/ث",
|
||||
"{rate} msg/s": "{rate} رسالة/ث",
|
||||
@@ -2767,7 +2766,7 @@
|
||||
"standard": "القياسي",
|
||||
"mini": "المصغّر",
|
||||
"COST UNKNOWN": "التكلفة غير معروفة",
|
||||
"ChatGPT OAuth session: {responses} response(s), {input} input and {output} output tokens, {captions} caption transcription(s) reported.": "جلسة ChatGPT OAuth: الاستجابات: {responses}، رموز الإدخال: {input}، رموز الإخراج: {output}، نسخ التسميات التوضيحية: {captions}.",
|
||||
"ChatGPT OAuth session: {responses} response(s), {input} input and {output} output tokens, {captions} caption transcription(s) reported.": "جلسة ChatGPT OAuth (حسب ما أُبلغ): الاستجابات: {responses}، رموز الإدخال: {input}، رموز الإخراج: {output}، عمليات النسخ النصي للتسميات التوضيحية: {captions}.",
|
||||
"USD cost and the API spend cap are unavailable for this auth mode.": "التكلفة بالدولار وحد إنفاق API غير متاحين في وضع المصادقة هذا.",
|
||||
"Usage is incomplete because a response was still in flight when the session ended.": "بيانات الاستخدام غير مكتملة لأن استجابة كانت ما تزال قيد الإرسال عند انتهاء الجلسة.",
|
||||
"Estimate is incomplete — a response was still in flight when the session ended, so its usage was never reported.": "التقدير غير مكتمل — كانت استجابة ما تزال قيد الإرسال عند انتهاء الجلسة، فلم يُبلَّغ عن استخدامها.",
|
||||
@@ -2927,8 +2926,8 @@
|
||||
"{label} loading": "{label}: جارٍ التحميل",
|
||||
"{label} error": "{label}: خطأ",
|
||||
"counted the first {returned} loaded records": "احتُسبت أول {returned} من السجلات المحمّلة",
|
||||
"counted {returned} of {total} loaded records": "احتُسب {returned} من {total} سجلًا محمّلًا",
|
||||
"{layers} just turned on — still loading, counts will rise": "{layers}: فُعّل للتو — ما زال قيد التحميل، وستزداد الأعداد",
|
||||
"counted {returned} of {total} loaded records": "احتُسب {returned} من أصل {total} من السجلات المحمّلة",
|
||||
"{layers} just turned on — still loading, counts will rise": "{layers}: تم التفعيل للتو — جارٍ التحميل، وستزداد الأعداد",
|
||||
"Contacts panel snapshot at {time} — the same retained cohort supplies the card, speech, and follow-up memory": "لقطة لوحة «الأهداف» عند {time} — المجموعة المحفوظة نفسها تغذّي البطاقة والكلام وذاكرة الأسئلة اللاحقة",
|
||||
"Contacts panel snapshot — the same retained cohort supplies the card, speech, and follow-up memory": "لقطة لوحة «الأهداف» — المجموعة المحفوظة نفسها تغذّي البطاقة والكلام وذاكرة الأسئلة اللاحقة",
|
||||
"Fly below {km} km to a covered region": "انخفض إلى ما دون {km} كم فوق منطقة مغطاة",
|
||||
@@ -3116,7 +3115,7 @@
|
||||
"KTS": "عقدة",
|
||||
"FT": "قدم",
|
||||
"FLT": "رحلات",
|
||||
"MIL": "عسكري",
|
||||
"MIL": "عسكرية",
|
||||
"SITE": "مواقع",
|
||||
"WX": "طقس",
|
||||
"MM": "مم",
|
||||
@@ -3142,7 +3141,7 @@
|
||||
"RTL-SDR tuner gain for the current mode": "كسب موالف RTL-SDR للوضع الحالي",
|
||||
"AUTO": "تلقائي",
|
||||
"MSG/S": "رسالة/ث",
|
||||
"HEARD": "المسموعة",
|
||||
"HEARD": "الملتقطة",
|
||||
"POSITIONED": "محددة الموضع",
|
||||
"FM MHZ": "FM MHz",
|
||||
"TUNE": "ضبط",
|
||||
|
||||
@@ -673,7 +673,6 @@
|
||||
"FIRE · {frp} MW": "INCENDIO · {frp} MW",
|
||||
"▲ {frp} MW": "▲ {frp} MW",
|
||||
"FIRE": "INCENDIO",
|
||||
"FIRES": "INCENDIOS",
|
||||
"{value} conf": "confianza {value}",
|
||||
"{value} ago": "hace {value}",
|
||||
"max {value} MW": "máx {value} MW",
|
||||
|
||||
@@ -135,7 +135,6 @@
|
||||
"NIGHT": "НОЧЬ",
|
||||
"▲ {frp} MW": "▲ {frp} МВт",
|
||||
"FIRE": "ПОЖАР",
|
||||
"FIRES": "ПОЖ.",
|
||||
"max {value} MW": "макс. {value} МВт",
|
||||
"new {value}": "последний {value}",
|
||||
"just now": "только что",
|
||||
|
||||
@@ -697,7 +697,6 @@
|
||||
"NIGHT": "夜间",
|
||||
"▲ {frp} MW": "▲ {frp} MW",
|
||||
"FIRE": "火点",
|
||||
"FIRES": "火点",
|
||||
"max {value} MW": "最大 {value} MW",
|
||||
"new {value}": "最新({value}前)",
|
||||
"{value}°N": "{value}°N",
|
||||
|
||||
@@ -692,7 +692,6 @@
|
||||
"NIGHT": "夜間",
|
||||
"▲ {frp} MW": "▲ {frp} MW",
|
||||
"FIRE": "火點",
|
||||
"FIRES": "火點",
|
||||
"max {value} MW": "最大 {value} MW",
|
||||
"new {value}": "最新({value}前)",
|
||||
"{value}°N": "{value}°N",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CCTV_AMBIENT_CARD_MAX } from '../../data/cctvLod.js';
|
||||
import { t } from '../../i18n/index.js';
|
||||
import { t, translateKnown } from '../../i18n/index.js';
|
||||
import { ACTIVE_FRAME_REFRESH_MS, IDLE_FRAME_REFRESH_MS } from './policy.js';
|
||||
import { headingHudToken, isHeadingEstimated } from './headingConfidence.js';
|
||||
import {
|
||||
@@ -8,6 +8,22 @@ import {
|
||||
isDatasheetFov,
|
||||
} from './modelSpecs.js';
|
||||
|
||||
/** The translated name of a camera view band (street, city, regional, global). */
|
||||
function viewBandLabel(band) {
|
||||
switch (band) {
|
||||
case 'street':
|
||||
return t('STREET', { context: 'view band' });
|
||||
case 'city':
|
||||
return t('CITY', { context: 'view band' });
|
||||
case 'regional':
|
||||
return t('REGIONAL', { context: 'view band' });
|
||||
case 'global':
|
||||
return t('GLOBAL', { context: 'view band' });
|
||||
default:
|
||||
return String(band).toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
export function createPresentation({
|
||||
state: layerState,
|
||||
services,
|
||||
@@ -73,16 +89,16 @@ export function createPresentation({
|
||||
layerState._showProjection ? t('PROJ MONITOR') : t('PROJ OFF'),
|
||||
layerState._coverageMode === 'viewshed' ? t('VIEWSHED') : null,
|
||||
t('CAL {value}', {
|
||||
value: calBadge.replace('-', ' ').toUpperCase(),
|
||||
value: translateKnown(calBadge.replace('-', ' ').toUpperCase()),
|
||||
}),
|
||||
health?.sourceKind
|
||||
? t('SRC {value}', {
|
||||
value: String(health.sourceKind).toUpperCase(),
|
||||
})
|
||||
: t('SRC {value}', {
|
||||
value: String(active.camera.feedType || 'image').toUpperCase(),
|
||||
}),
|
||||
t('{value} CONTEXT', { value: viewBand.toUpperCase() }),
|
||||
t('SRC {value}', {
|
||||
value: translateKnown(
|
||||
String(
|
||||
health?.sourceKind || active.camera.feedType || 'image',
|
||||
).toUpperCase(),
|
||||
),
|
||||
}),
|
||||
t('{value} CONTEXT', { value: viewBandLabel(viewBand) }),
|
||||
// Identified hardware: append the model's datasheet specs + attribution.
|
||||
active.camera.spec
|
||||
? t('{spec} · SPECS: CCTV-DATABASE.COM', {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as Cesium from 'cesium';
|
||||
import { formatNumber, isolate, t } from '../../i18n/index.js';
|
||||
import { formatNumber, getLocale, isolate, t, tn } from '../../i18n/index.js';
|
||||
import {
|
||||
satelliteShortName,
|
||||
fireDetectionKey,
|
||||
@@ -407,7 +407,6 @@ export function createModel({
|
||||
|
||||
function buildCellCard(candidate, nowMs) {
|
||||
const cell = candidate.cell;
|
||||
const noun = cell.count === 1 ? t('FIRE') : t('FIRES');
|
||||
const parts = [t('max {value} MW', { value: formatFrpLabel(cell.maxFrp) })];
|
||||
if (cell.newestAcqMs > 0) {
|
||||
const age = formatAgeLabel(nowMs - cell.newestAcqMs);
|
||||
@@ -419,7 +418,12 @@ export function createModel({
|
||||
cullPosition: candidate.cullPosition || candidate.position,
|
||||
gapPx: 10,
|
||||
accent: candidate.accent || accentForSeverity('yellow'),
|
||||
title: `${cell.count} ${noun}`,
|
||||
// The count picks the plural form of the language ("حريقان (2)",
|
||||
// "14 حريقًا", "14 ПОЖАРОВ"); the card shows it in capitals like the
|
||||
// other card titles.
|
||||
title: tn(cell.count, '{n} fire', '{n} fires', {
|
||||
n: cell.count,
|
||||
}).toLocaleUpperCase(getLocale()),
|
||||
details: [parts.join(' · ')],
|
||||
selected: false,
|
||||
priority: Number(cell.maxFrp) || 0,
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
min-height: 3.55rem;
|
||||
padding: 0.6rem 0.7rem;
|
||||
color: rgba(225, 244, 248, 0.92);
|
||||
text-align: left;
|
||||
text-align: start;
|
||||
background: rgba(29, 69, 81, 0.18);
|
||||
border: 1px solid rgba(100, 200, 220, 0.18);
|
||||
border-radius: 0.42rem;
|
||||
|
||||
@@ -288,7 +288,7 @@
|
||||
content: counter(gev-referent);
|
||||
display: inline-block;
|
||||
min-width: 0.9rem;
|
||||
margin-right: 0.3rem;
|
||||
margin-inline-end: 0.3rem;
|
||||
color: rgba(54, 220, 255, 0.72);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.52rem;
|
||||
|
||||
+10
-6
@@ -35,15 +35,19 @@ export function formatQuantity(value, unit, options) {
|
||||
|
||||
/**
|
||||
* A legend stop such as "0.1", "-40" or "300+" in the active language.
|
||||
* Anything that is not a plain number is shown as given.
|
||||
* Anything that is not a plain number is shown as given. In right-to-left
|
||||
* text the stop is isolated, so its sign stays where it is written ("300+",
|
||||
* "-40") instead of moving to the other side of the number.
|
||||
*/
|
||||
export function formatScaleLabel(label) {
|
||||
const match = /^(-?\d+(?:\.\d+)?)(\+?)$/.exec(String(label ?? ''));
|
||||
if (!match) return String(label ?? '');
|
||||
const decimals = match[1].split('.')[1]?.length || 0;
|
||||
return `${formatNumber(Number(match[1]), {
|
||||
useGrouping: false,
|
||||
minimumFractionDigits: decimals,
|
||||
maximumFractionDigits: decimals,
|
||||
})}${match[2]}`;
|
||||
return isolate(
|
||||
`${formatNumber(Number(match[1]), {
|
||||
useGrouping: false,
|
||||
minimumFractionDigits: decimals,
|
||||
maximumFractionDigits: decimals,
|
||||
})}${match[2]}`,
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { t } from '../i18n/index.js';
|
||||
import { formatNumber, t } from '../i18n/index.js';
|
||||
|
||||
// The assistant's name on its card. i18n-ignore: product name
|
||||
const ASSISTANT_NAME = 'GEV';
|
||||
@@ -27,6 +27,10 @@ export function voiceStatusLabel(status) {
|
||||
}
|
||||
|
||||
/** Build the voice control independently of its connection backend. */
|
||||
/** "5 minutes" in the UI language, with the count's plural form ("15 دقيقة"). */
|
||||
const minutesLabel = (count) =>
|
||||
formatNumber(count, { style: 'unit', unit: 'minute', unitDisplay: 'long' });
|
||||
|
||||
export function createVoiceControl({ reset = false, panel = false } = {}) {
|
||||
let root = document.getElementById('gev-voice-control');
|
||||
if (root && reset) {
|
||||
@@ -118,7 +122,7 @@ export function createVoiceControl({ reset = false, panel = false } = {}) {
|
||||
<label class="gev-voice-preference gev-voice-setting-title" for="gev-voice-timeout-select">${t('Voice inactivity timeout')}</label>
|
||||
<div class="gev-voice-timeout-controls">
|
||||
<select id="gev-voice-timeout-select" aria-describedby="gev-voice-timeout-note gev-voice-timeout-status">
|
||||
<option value="3">3 ${t('Minutes')}</option><option value="5" selected>5 ${t('Minutes')}</option><option value="10">10 ${t('Minutes')}</option><option value="15">15 ${t('Minutes')}</option>
|
||||
<option value="3">${minutesLabel(3)}</option><option value="5" selected>${minutesLabel(5)}</option><option value="10">${minutesLabel(10)}</option><option value="15">${minutesLabel(15)}</option>
|
||||
<option value="custom">${t('Custom')}</option><option value="0">${t('None')}</option>
|
||||
</select>
|
||||
<label class="gev-voice-timeout-unit" for="gev-voice-timeout-input">${t('Minutes')}</label>
|
||||
|
||||
Reference in new issue
Block a user