feat(routing): pure Arabic localization for all navigation instructions (translate Continue onto, toward, keep right, etc.)

This commit is contained in:
Hamza-Ayed
2026-08-18 12:18:06 +03:00
parent 57e3da7ea4
commit 0a854c4302
+113 -4
View File
@@ -241,6 +241,9 @@ export class MapsService {
const startIdx = Math.min(interval[0], coords.length - 1);
const endIdx = Math.min(interval[1], coords.length - 1);
// 1. Localize text into 100% fluent Arabic (Translate "Continue onto", "toward", "Keep right", etc.)
const localizedBaseText = this.localizeInstructionToArabic(inst.text);
if (startIdx < endIdx) {
const startCoord = coords[startIdx]; // [lng, lat]
const endCoord = coords[endIdx];
@@ -262,10 +265,10 @@ export class MapsService {
if (slopePercent >= 9) {
warning_ar = `⚠️ تنبيه: صعود حاد (+${slopePercent}%)`;
steepWarnings.push({ text: inst.text, slopePercent, type: 'incline', street: inst.street_name });
steepWarnings.push({ text: localizedBaseText, slopePercent, type: 'incline', street: inst.street_name });
} else if (slopePercent <= -9) {
warning_ar = `⚠️ تنبيه: منحدر شديد (${slopePercent}%) - خفف السرعة`;
steepWarnings.push({ text: inst.text, slopePercent, type: 'decline', street: inst.street_name });
steepWarnings.push({ text: localizedBaseText, slopePercent, type: 'decline', street: inst.street_name });
}
return {
@@ -273,11 +276,14 @@ export class MapsService {
slopePercent,
elevationChangeMeters: Math.round(elevDiff),
slopeWarning: warning_ar || undefined,
text: warning_ar ? `${inst.text} (${warning_ar})` : inst.text
text: warning_ar ? `${localizedBaseText} (${warning_ar})` : localizedBaseText
};
}
return inst;
return {
...inst,
text: localizedBaseText
};
});
return {
@@ -293,6 +299,109 @@ export class MapsService {
};
}
/**
* Translates any English phrases from routing engines (GraphHopper) into natural, fluent Arabic.
*/
private localizeInstructionToArabic(rawText: string): string {
if (!rawText) return '';
let text = rawText.trim();
// 1. English Directional & Maneuver Replacements
const phrases: [RegExp, string][] = [
// Continuations
[/^Continue onto\s+/i, 'تابع السير في '],
[/^Continue on\s+/i, 'تابع السير في '],
[/^Continue straight\s+/i, 'تابع السير بشكل مستقيم في '],
[/^Continue straight$/i, 'تابع السير للأمام مباشرة'],
[/^Continue\s*$/i, 'تابع السير للأمام'],
// Roundabouts
[/في الدوران\s*،\s*أتخذ مخرج\s+(\d+)\s+من خلال/i, 'عند الدوار، اسلك المخرج $1 عبر'],
[/في الدوران\s*،\s*اتخذ مخرج\s+(\d+)\s+من خلال/i, 'عند الدوار، اسلك المخرج $1 عبر'],
[/في الدوران\s*،\s*أتخذ مخرج\s+(\d+)/i, 'عند الدوار، اسلك المخرج $1'],
[/في الدوران\s*،\s*اتخذ مخرج\s+(\d+)/i, 'عند الدوار، اسلك المخرج $1'],
[/At roundabout, take exit\s+(\d+)\s+onto/i, 'عند الدوار، اسلك المخرج $1 عبر'],
[/At roundabout, take exit\s+(\d+)/i, 'عند الدوار، اسلك المخرج $1'],
[/In roundabout, take exit\s+(\d+)/i, 'عند الدوار، اسلك المخرج $1'],
// Turns
[/^Turn sharp right onto\s+/i, 'انعطف يميناً بشكل حاد إلى '],
[/^Turn slight right onto\s+/i, 'انعطف يميناً بشكل طفيف إلى '],
[/^Turn right onto\s+/i, 'اتجه يميناً إلى '],
[/^Turn sharp right/i, 'انعطف يميناً بشكل حاد'],
[/^Turn slight right/i, 'انعطف يميناً بشكل طفيف'],
[/^Turn right/i, 'اتجه يميناً'],
[/^Turn sharp left onto\s+/i, 'انعطف يساراً بشكل حاد إلى '],
[/^Turn slight left onto\s+/i, 'انعطف يساراً بشكل طفيف إلى '],
[/^Turn left onto\s+/i, 'اتجه يساراً إلى '],
[/^Turn sharp left/i, 'انعطف يساراً بشكل حاد'],
[/^Turn slight left/i, 'انعطف يساراً بشكل طفيف'],
[/^Turn left/i, 'اتجه يساراً'],
// Keeps
[/^Keep right toward\s+/i, 'الزم اليمين باتجاه '],
[/^Keep right onto\s+/i, 'الزم اليمين في '],
[/^Keep right/i, 'الزم اليمين'],
[/^احفظ اليمين toward\s+/i, 'الزم اليمين باتجاه '],
[/^احفظ اليمين خلال\s+/i, 'الزم اليمين عبر '],
[/^احفظ اليمين/i, 'الزم اليمين'],
[/^Keep left toward\s+/i, 'الزم اليسار باتجاه '],
[/^Keep left onto\s+/i, 'الزم اليسار في '],
[/^Keep left/i, 'الزم اليسار'],
[/^احفظ الشمال toward\s+/i, 'الزم اليسار باتجاه '],
[/^احفظ الشمال خلال\s+/i, 'الزم اليسار عبر '],
[/^احفظ الشمال/i, 'الزم اليسار'],
// U-Turns
[/^Make a U-turn\s+/i, 'قم بالدوران للخلف (U-turn) عند '],
[/^Make a U-turn/i, 'قم بالدوران للخلف'],
[/^U-turn/i, 'دوران للخلف'],
// Head / Bearings
[/^Head north onto\s+/i, 'اتجه شمالاً في '],
[/^Head south onto\s+/i, 'اتجه جنوباً في '],
[/^Head east onto\s+/i, 'اتجه شرقاً في '],
[/^Head west onto\s+/i, 'اتجه غرباً في '],
[/^Head northeast onto\s+/i, 'اتجه نحو الشمال الشرقي في '],
[/^Head northwest onto\s+/i, 'اتجه نحو الشمال الغربي في '],
[/^Head southeast onto\s+/i, 'اتجه نحو الجنوب الشرقي في '],
[/^Head southwest onto\s+/i, 'اتجه نحو الجنوب الغربي في '],
[/^Head north/i, 'اتجه شمالاً'],
[/^Head south/i, 'اتجه جنوباً'],
[/^Head east/i, 'اتجه شرقاً'],
[/^Head west/i, 'اتجه غرباً'],
[/^Head northeast/i, 'اتجه شمال شرق'],
[/^Head northwest/i, 'اتجه شمال غرب'],
[/^Head southeast/i, 'اتجه جنوب شرق'],
[/^Head southwest/i, 'اتجه جنوب غرب'],
// Toward / Onto / Through prepositions
[/\btoward\b/gi, 'باتجاه'],
[/\btowards\b/gi, 'باتجاه'],
[/\bonto\b/gi, 'في'],
[/\bthrough\b/gi, 'عبر'],
// Destinations & Finish
[/^Arrive at destination/i, 'الوصول إلى الوجهة'],
[/^Reached destination/i, 'تم الوصول إلى الوجهة'],
[/^Destination/i, 'الوصول إلى الوجهة'],
[/^النهاية/i, 'الوصول إلى الوجهة']
];
for (const [regex, replacement] of phrases) {
text = text.replace(regex, replacement);
}
// Clean up excessive whitespace
text = text.replace(/\s+/g, ' ').trim();
return text;
}
private estimateElevation(lat: number, lng: number): number {
if (lng < 35.6 && lat < 32.2 && lat > 31.0) {
return -400 + Math.abs(lng - 35.5) * 3000;