كيفية التعامل مع الاحتياطي اللغوي عند عدم توفر اللغة المفضلة
اختيار اللغات المدعومة تلقائياً عندما يفضل المستخدمون لغات غير مدعومة
مقدمة
لا يدعم كل تطبيق ويب جميع لغات العالم. عندما يفضل المستخدم لغة لا يدعمها تطبيقك، تحتاج إلى آلية احتياطية لعرض المحتوى باللغة البديلة الأفضل بدلاً من إظهار أخطاء أو نصوص غير مترجمة.
الاحتياطي اللغوي هو عملية اختيار لغة بديلة عندما تكون اللغة المفضلة غير متوفرة. تتعامل واجهة برمجة التطبيقات Intl في JavaScript مع هذا تلقائياً من خلال قبول خيارات لغات متعددة واختيار أول لغة مدعومة. يضمن هذا أن يعرض تطبيقك دائماً محتوى منسقاً بشكل صحيح، حتى عندما لا تكون اللغة المفضلة بالضبط متوفرة.
يشرح هذا الدرس كيفية عمل الاحتياطي اللغوي في JavaScript، وكيفية تنفيذه بفعالية، وكيفية بناء منطق احتياطي مخصص للتطبيقات ذات متطلبات دعم لغوي محددة.
المشكلة مع اللغات غير المدعومة
عندما تمرر معرف لغة إلى واجهة برمجة التطبيقات Intl، يجب أن يدعم محرك JavaScript تلك اللغة لتنسيق المحتوى بشكل صحيح. إذا طلبت التنسيق للنرويجية نينورسك لكن المحرك يدعم فقط النرويجية بوكمول، يحتاج المنسق إلى طريقة للتعامل مع هذا بشكل سلس.
بدون احتياطي، ستفشل التطبيقات في عرض المحتوى أو ستظهر نصوصاً غير مترجمة عند مواجهة لغات غير مدعومة. سيواجه المستخدمون من المناطق ذات المتغيرات اللغوية الأقل شيوعاً واجهات معطلة.
لنأخذ مثالاً على مستخدم يتحدث الفرنسية الكندية. إذا كان تطبيقك يدعم فقط الفرنسية الأوروبية، فأنت تريد أن يستخدم المنسق اصطلاحات الفرنسية الأوروبية بدلاً من الفشل تماماً. على الرغم من أنها ليست مثالية، إلا أن هذا يوفر تجربة أفضل من عدم وجود توطين على الإطلاق.
كيفية معالجة واجهة Intl API للاحتياطي تلقائيًا
يقبل كل منشئ Intl إما سلسلة لغة واحدة أو مصفوفة من سلاسل اللغات. عند تمرير مصفوفة، يقوم وقت التشغيل بتقييم كل لغة بالترتيب ويستخدم أول لغة يدعمها.
const locales = ["fr-CA", "fr-FR", "en-US"];
const formatter = new Intl.DateTimeFormat(locales);
const date = new Date("2025-03-15");
console.log(formatter.format(date));
// Uses fr-CA if available
// Falls back to fr-FR if fr-CA is not available
// Falls back to en-US if neither French variant is available
يفحص وقت التشغيل المصفوفة من اليسار إلى اليمين. إذا كان يدعم الفرنسية الكندية، فإنه يستخدمها. إذا لم يكن كذلك، فإنه يحاول الفرنسية الأوروبية. إذا لم يكن أي من المتغيرات الفرنسية متاحًا، فإنه يعود إلى الإنجليزية الأمريكية.
يعني هذا الاحتياطي التلقائي أنك لست بحاجة إلى التحقق من الدعم يدويًا أو معالجة الأخطاء عند طلب لغات محددة. تضمن واجهة Intl API أنها ستختار لغة مدعومة أو تعود إلى الإعداد الافتراضي للنظام.
توفير خيارات لغات متعددة
أبسط طريقة لتنفيذ الاحتياطي هي تمرير مصفوفة من اللغات بترتيب الأفضلية. يعمل هذا مع جميع منشئات Intl بما في ذلك DateTimeFormat، NumberFormat، Collator، وغيرها.
const locales = ["es-MX", "es-ES", "es", "en"];
const numberFormatter = new Intl.NumberFormat(locales, {
style: "currency",
currency: "USD"
});
console.log(numberFormatter.format(1234.56));
// Uses Mexican Spanish if available
// Falls back to European Spanish
// Falls back to generic Spanish
// Falls back to English as final option
يوفر هذا النمط مسار تدهور تدريجي. يحصل المستخدمون على المحتوى بلهجتهم المفضلة إذا كانت متاحة، ثم متغير أوسع من لغتهم، ثم لغة احتياطية شائعة.
الترتيب مهم. يختار وقت التشغيل أول لغة يدعمها، لذا ضع اللغات الأكثر تحديدًا وتفضيلاً أولاً.
فهم كيفية عمل مطابقة اللغة
عند توفير لغات متعددة، يستخدم وقت تشغيل JavaScript خوارزمية مطابقة اللغة لاختيار أفضل خيار متاح. تقارن هذه الخوارزمية اللغات المطلوبة مع مجموعة اللغات التي يدعمها وقت التشغيل.
إذا تطابقت لغة مطلوبة تمامًا مع لغة مدعومة، فإن وقت التشغيل يستخدمها فورًا. إذا لم يكن هناك تطابق تام، فقد يختار وقت التشغيل لغة ذات صلة بناءً على رموز اللغة والمنطقة.
على سبيل المثال، إذا طلبت en-AU (الإنجليزية الأسترالية) لكن بيئة التشغيل تدعم فقط en-US و en-GB، فسيتم اختيار أحد متغيرات اللغة الإنجليزية هذه بدلاً من الرجوع إلى لغة مختلفة تماماً.
const locales = ["en-AU", "en"];
const formatter = new Intl.DateTimeFormat(locales);
const resolvedLocale = formatter.resolvedOptions().locale;
console.log(resolvedLocale);
// Might show "en-US" or "en-GB" depending on the runtime
// The runtime selected a supported English variant
تُرجع الدالة resolvedOptions() اللغة الفعلية التي يستخدمها المُنسِّق. يتيح لك ذلك التحقق من اللغة التي تم اختيارها بعد الرجوع الاحتياطي.
التحقق من اللغات المدعومة
تتحقق الدالة الثابتة supportedLocalesOf() من اللغات المدعومة من قائمة معينة بواسطة مُنشئ Intl محدد. تُرجع هذه الدالة مصفوفة تحتوي فقط على اللغات المدعومة.
const requestedLocales = ["fr-CA", "fr-FR", "de-DE", "ja-JP"];
const supportedLocales = Intl.DateTimeFormat.supportedLocalesOf(requestedLocales);
console.log(supportedLocales);
// Output depends on runtime support
// Example: ["fr-FR", "de-DE", "ja-JP"]
// Canadian French was not supported, others were
تقوم هذه الدالة بتصفية اللغات المطلوبة لإظهار تلك التي يمكن لبيئة التشغيل استخدامها دون الرجوع إلى الإعدادات الافتراضية. يتم إزالة اللغات غير المدعومة من المصفوفة المُرجعة.
يمكنك استخدام هذه الدالة للتحقق من الدعم قبل إنشاء المُنسِّقات، أو لعرض خيارات اللغة المتاحة للمستخدمين.
const availableLocales = ["en-US", "es-MX", "fr-FR", "de-DE", "ja-JP"];
const supported = Intl.NumberFormat.supportedLocalesOf(availableLocales);
console.log("This runtime supports:", supported);
// Shows which of your application locales work in this environment
لكل مُنشئ Intl دالة supportedLocalesOf() خاصة به لأن دعم اللغات قد يختلف بين ميزات التدويل المختلفة. قد تدعم بيئة التشغيل اللغة الفرنسية لتنسيق الأرقام ولكن ليس لتقسيم النصوص.
بناء سلاسل الرجوع الاحتياطي من معرّفات اللغة
عندما تعلم أن تطبيقك يدعم لغات محددة، يمكنك بناء سلسلة رجوع احتياطي تصبح تدريجياً أقل تحديداً. يبدأ هذا النمط بمعرّف لغة كامل ويزيل المكونات حتى يجد تطابقاً.
function buildFallbackChain(locale) {
const chain = [locale];
const parts = locale.split("-");
if (parts.length > 1) {
chain.push(parts[0]);
}
chain.push("en");
return chain;
}
const fallbacks = buildFallbackChain("zh-Hans-CN");
console.log(fallbacks);
// ["zh-Hans-CN", "zh", "en"]
const formatter = new Intl.DateTimeFormat(fallbacks);
// Tries Simplified Chinese for China
// Falls back to generic Chinese
// Falls back to English
تُنشئ هذه الدالة سلسلة رجوع احتياطي من خلال استخراج رمز اللغة من معرّف اللغة وإضافة رجوع احتياطي نهائي للغة الإنجليزية. يمكنك توسيع هذا المنطق ليشمل قواعد رجوع احتياطي أكثر تطوراً بناءً على اللغات المدعومة في تطبيقك.
بالنسبة للتطبيقات التي تدعم متغيرات متعددة من اللغة، قد ترغب في الرجوع إلى اللهجات ذات الصلة قبل الانتقال إلى الإنجليزية.
function buildSmartFallbackChain(locale) {
const chain = [locale];
if (locale.startsWith("es-")) {
chain.push("es-MX", "es-ES", "es");
} else if (locale.startsWith("fr-")) {
chain.push("fr-FR", "fr-CA", "fr");
} else if (locale.startsWith("zh-")) {
chain.push("zh-Hans-CN", "zh-Hant-TW", "zh");
}
const parts = locale.split("-");
if (parts.length > 1 && !chain.includes(parts[0])) {
chain.push(parts[0]);
}
if (!chain.includes("en")) {
chain.push("en");
}
return chain;
}
const fallbacks = buildSmartFallbackChain("es-AR");
console.log(fallbacks);
// ["es-AR", "es-MX", "es-ES", "es", "en"]
// Tries Argentinian Spanish
// Falls back to Mexican Spanish
// Falls back to European Spanish
// Falls back to generic Spanish
// Falls back to English
يضمن هذا النهج أن يرى المستخدمون المحتوى بلهجة ذات صلة بلغتهم قبل الرجوع إلى الإنجليزية.
اختيار خوارزمية مطابقة اللغة
تدعم واجهة برمجة التطبيقات Intl خوارزميتين لمطابقة اللغة: البحث والملاءمة الأفضل. يمكنك تحديد الخوارزمية المراد استخدامها من خلال خيار localeMatcher عند إنشاء أدوات التنسيق.
تتبع خوارزمية البحث مواصفات BCP 47 Lookup. تقوم بإجراء مطابقة صارمة من خلال مقارنة معرفات اللغة بشكل منهجي واختيار أول تطابق تام.
const locales = ["de-DE", "en-US"];
const formatter = new Intl.NumberFormat(locales, {
localeMatcher: "lookup"
});
console.log(formatter.resolvedOptions().locale);
// Uses strict lookup matching rules
تسمح خوارزمية الملاءمة الأفضل لبيئة التشغيل باختيار لغة باستخدام منطق المطابقة الخاص بها. يمكن لهذه الخوارزمية اتخاذ قرارات ذكية حول اللغة التي تخدم احتياجات المستخدم بشكل أفضل، حتى لو لم تكن مطابقة تامة.
const locales = ["de-DE", "en-US"];
const formatter = new Intl.NumberFormat(locales, {
localeMatcher: "best fit"
});
console.log(formatter.resolvedOptions().locale);
// Uses runtime's best fit algorithm
// Might select a related locale more intelligently
الخوارزمية الافتراضية هي الملاءمة الأفضل. يجب على معظم التطبيقات استخدام الإعداد الافتراضي لأنه يوفر نتائج أفضل عبر بيئات تشغيل JavaScript المختلفة. استخدم البحث فقط عندما تحتاج إلى سلوك مطابقة صارم ومتوقع.
استخدام تفضيلات لغة المتصفح للرجوع التلقائي
تُرجع خاصية navigator.languages مصفوفة من اللغات المفضلة للمستخدم مرتبة حسب الأفضلية. يمكنك تمرير هذه المصفوفة مباشرة إلى منشئات Intl لتنفيذ الرجوع التلقائي بناءً على إعدادات المتصفح.
const formatter = new Intl.DateTimeFormat(navigator.languages);
const date = new Date("2025-03-15");
console.log(formatter.format(date));
// Automatically uses user's preferred supported language
يتيح هذا النهج للمتصفح التعامل مع جميع منطق الرجوع. إذا لم يكن تفضيل المستخدم الأول مدعومًا، فإن واجهة برمجة التطبيقات Intl تحاول تلقائيًا تفضيله الثاني، ثم الثالث، وهكذا.
يعمل هذا النمط بشكل جيد عندما تريد احترام جميع تفضيلات اللغة الخاصة بالمستخدم دون بناء سلاسل احتياطية يدويًا.
console.log(navigator.languages);
// ["fr-CA", "fr", "en-US", "en"]
const numberFormatter = new Intl.NumberFormat(navigator.languages, {
style: "currency",
currency: "USD"
});
console.log(numberFormatter.format(1234.56));
// Tries Canadian French first
// Falls back through the user's complete preference list
تقوم واجهة Intl API بتقييم كل لغة في المصفوفة وتحديد أول لغة مدعومة، مما يجعل هذا حلاً قويًا للتعامل مع تفضيلات المستخدمين المتنوعة.
الجمع بين دعم التطبيق وتفضيلات المستخدم
بالنسبة للتطبيقات ذات الدعم المحدود للغات المحلية، يمكنك تصفية تفضيلات المستخدم لمطابقة اللغات المحلية المدعومة لديك قبل إنشاء أدوات التنسيق. يضمن هذا أنك تحاول فقط استخدام اللغات المحلية التي يمكن لتطبيقك التعامل معها.
const supportedLocales = ["en-US", "es-MX", "fr-FR", "de-DE"];
function findBestLocale(userPreferences, appSupported) {
const preferences = userPreferences.map(pref => {
const parts = pref.split("-");
return [pref, parts[0]];
}).flat();
for (const pref of preferences) {
if (appSupported.includes(pref)) {
return pref;
}
}
return appSupported[0];
}
const userLocale = findBestLocale(navigator.languages, supportedLocales);
const formatter = new Intl.DateTimeFormat(userLocale);
console.log(formatter.resolvedOptions().locale);
// Selected locale matches both user preference and app support
تجد هذه الدالة أول تطابق بين تفضيلات المستخدم واللغات المحلية المدعومة، بما في ذلك محاولة استخدام رموز اللغة بدون رموز المنطقة لمطابقة أوسع.
للحصول على مطابقة أكثر تطورًا، يمكنك التحقق من أي من تفضيلات المستخدم مدعومة بواسطة واجهة Intl API في بيئة التشغيل هذه.
const supportedLocales = ["en-US", "es-MX", "fr-FR", "de-DE"];
function findBestSupportedLocale(userPreferences, appSupported) {
const runtimeSupported = Intl.DateTimeFormat.supportedLocalesOf(appSupported);
for (const pref of userPreferences) {
if (runtimeSupported.includes(pref)) {
return pref;
}
const lang = pref.split("-")[0];
const match = runtimeSupported.find(s => s.startsWith(lang));
if (match) {
return match;
}
}
return runtimeSupported[0] || "en";
}
const userLocale = findBestSupportedLocale(navigator.languages, supportedLocales);
const formatter = new Intl.DateTimeFormat(userLocale);
يضمن هذا النهج أن اللغة المحلية المحددة مدعومة من قبل كل من تطبيقك وبيئة تشغيل JavaScript.
التعامل مع الحالات التي لا تتطابق فيها أي لغة محلية
إذا لم تكن أي من اللغات المحلية المطلوبة مدعومة، تعود واجهة Intl API إلى اللغة المحلية الافتراضية للنظام. يختلف هذا الإعداد الافتراضي حسب البيئة ويتم تحديده بواسطة نظام التشغيل أو المتصفح أو إعدادات Node.js.
const unsupportedLocales = ["non-existent-locale"];
const formatter = new Intl.DateTimeFormat(unsupportedLocales);
console.log(formatter.resolvedOptions().locale);
// Shows the system default locale
// Might be "en-US" or another locale depending on the system
يضمن الإعداد الافتراضي للنظام أن أدوات التنسيق تعمل دائمًا، حتى مع قوائم اللغات المحلية غير الصالحة أو غير المدعومة تمامًا. لن يطرح تطبيقك أخطاء بسبب مشكلات اللغة المحلية.
لضمان احتياطي محدد بدلاً من الاعتماد على الإعداد الافتراضي للنظام، قم دائمًا بتضمين لغة محلية مدعومة على نطاق واسع مثل en أو en-US في نهاية مصفوفة اللغات المحلية الخاصة بك.
const locales = ["xyz-INVALID", "en"];
const formatter = new Intl.DateTimeFormat(locales);
console.log(formatter.resolvedOptions().locale);
// Will use "en" since the first locale is invalid
// Guaranteed fallback to English instead of system default
يجعل هذا النمط سلوك تطبيقك أكثر قابلية للتنبؤ عبر البيئات المختلفة.
أنماط عملية لتطبيقات الإنتاج
عند بناء تطبيقات الإنتاج، قم بدمج استراتيجيات احتياطية متعددة لضمان معالجة قوية للغات عبر قواعد مستخدمين متنوعة.
ينشئ النمط الشائع منسقات بسلسلة احتياطية كاملة تتضمن تفضيلات المستخدم واللغات المدعومة في التطبيق وخيار احتياطي نهائي مضمون.
class LocaleManager {
constructor(supportedLocales) {
this.supportedLocales = supportedLocales;
this.defaultLocale = "en-US";
}
buildLocaleChain(userPreference) {
const chain = [];
if (userPreference) {
chain.push(userPreference);
const lang = userPreference.split("-")[0];
if (lang !== userPreference) {
chain.push(lang);
}
}
chain.push(...navigator.languages);
chain.push(...this.supportedLocales);
chain.push(this.defaultLocale);
const unique = [...new Set(chain)];
return unique;
}
createDateFormatter(userPreference, options = {}) {
const locales = this.buildLocaleChain(userPreference);
return new Intl.DateTimeFormat(locales, options);
}
createNumberFormatter(userPreference, options = {}) {
const locales = this.buildLocaleChain(userPreference);
return new Intl.NumberFormat(locales, options);
}
}
const manager = new LocaleManager(["en-US", "es-MX", "fr-FR", "de-DE"]);
const dateFormatter = manager.createDateFormatter("pt-BR");
console.log(dateFormatter.resolvedOptions().locale);
// Uses comprehensive fallback chain
// Tries Portuguese for Brazil
// Falls back to Portuguese
// Falls back through navigator.languages
// Falls back through supported locales
// Guaranteed to use en-US if nothing else matches
تغلف هذه الفئة منطق اللغة الاحتياطية وتضمن سلوكاً متسقاً عبر تطبيقك.
بالنسبة للتطبيقات التي تحتاج إلى الاستجابة لتغييرات لغة المستخدم في وقت التشغيل، قم بدمج مدير اللغة مع مستمعي الأحداث.
class LocaleAwareFormatter {
constructor(supportedLocales) {
this.supportedLocales = supportedLocales;
this.updateFormatters();
window.addEventListener("languagechange", () => {
this.updateFormatters();
});
}
updateFormatters() {
const locales = [...navigator.languages, ...this.supportedLocales, "en"];
this.dateFormatter = new Intl.DateTimeFormat(locales);
this.numberFormatter = new Intl.NumberFormat(locales);
}
formatDate(date) {
return this.dateFormatter.format(date);
}
formatNumber(number) {
return this.numberFormatter.format(number);
}
}
const formatter = new LocaleAwareFormatter(["en-US", "es-MX", "fr-FR"]);
console.log(formatter.formatDate(new Date()));
// Automatically updates when user changes language preferences
ينشئ هذا النمط منسقات تظل متزامنة مع تغييرات لغة المتصفح، مما يضمن أن تطبيقك يعرض المحتوى دائماً وفقاً للتفضيلات الحالية.
الخلاصة
يضمن الخيار الاحتياطي للغة أن تطبيقك يعرض محتوى منسقاً بشكل صحيح حتى عندما يفضل المستخدمون لغات لا تدعمها صراحةً. تتعامل واجهة Intl API مع الخيار الاحتياطي تلقائياً من خلال قبول مصفوفات من تفضيلات اللغة واختيار الخيار المدعوم الأول.
المفاهيم الأساسية:
- مرر مصفوفات اللغات إلى منشئات Intl للخيار الاحتياطي التلقائي
- يختار وقت التشغيل أول لغة يدعمها من المصفوفة
- استخدم
supportedLocalesOf()للتحقق من اللغات المتاحة - قم ببناء سلاسل احتياطية تتقدم من لغات محددة إلى عامة
- يتحكم خيار
localeMatcherفي خوارزمية المطابقة - مرر
navigator.languagesمباشرةً للمعالجة التلقائية لتفضيلات المستخدم - قم دائماً بتضمين خيار احتياطي نهائي مدعوم على نطاق واسع مثل الإنجليزية
- يعود وقت التشغيل إلى الإعدادات الافتراضية للنظام عندما لا تتطابق أي لغات
استخدم الخيار الاحتياطي التلقائي مع مصفوفات اللغات لمعظم التطبيقات. قم بتنفيذ منطق احتياطي مخصص عندما تحتاج إلى تحكم محدد في اللغات التي يتم تجربتها وبأي ترتيب.