كيفية التعامل مع الرجوع الاحتياطي للغة المحلية عندما تكون اللغة المفضلة غير متوفرة

اختيار اللغات المدعومة تلقائيًا عندما يفضل المستخدمون لغات محلية غير مدعومة

مقدمة

ليس كل تطبيق ويب يدعم كل لغة في العالم. عندما يفضل المستخدم لغة لا يدعمها تطبيقك، تحتاج إلى آلية احتياطية لعرض المحتوى باللغة الأفضل التالية بدلاً من عرض أخطاء أو نص غير مترجم.

الانتقال الاحتياطي للغة المحلية هو عملية اختيار لغة محلية بديلة عندما تكون اللغة المحلية المفضلة غير متوفرة. تتعامل واجهة برمجة التطبيقات Intl في جافا سكريبت مع هذا تلقائيًا من خلال قبول خيارات متعددة للغة المحلية واختيار أول لغة تدعمها. هذا يضمن أن تطبيقك يعرض دائمًا محتوى منسقًا بشكل صحيح، حتى عندما تكون اللغة المحلية المفضلة بالضبط غير متوفرة.

يشرح هذا الدرس كيفية عمل الانتقال الاحتياطي للغة المحلية في جافا سكريبت، وكيفية تنفيذه بفعالية، وكيفية بناء منطق انتقال احتياطي مخصص للتطبيقات ذات متطلبات دعم اللغة المحلية المحددة.

مشكلة اللغات المحلية غير المدعومة

عندما تمرر معرف لغة محلية إلى واجهة برمجة التطبيقات Intl، يجب أن يدعم وقت تشغيل جافا سكريبت تلك اللغة المحلية لتنسيق المحتوى بشكل صحيح. إذا طلبت تنسيقًا للنرويجية نينورسك ولكن وقت التشغيل يدعم فقط النرويجية بوكمول، فإن المنسق يحتاج إلى طريقة للتعامل مع هذا بسلاسة.

بدون الانتقال الاحتياطي، قد تفشل التطبيقات في عرض المحتوى أو تظهر نصًا غير مترجم عند مواجهة لغات محلية غير مدعومة. سيواجه المستخدمون من المناطق ذات متغيرات اللغة الأقل شيوعًا واجهات معطلة.

فكر في مستخدم يتحدث الفرنسية الكندية. إذا كان تطبيقك يدعم فقط الفرنسية الأوروبية، فأنت تريد من المنسق استخدام اتفاقيات الفرنسية الأوروبية بدلاً من الفشل تمامًا. على الرغم من أنها ليست مثالية، إلا أنها توفر تجربة أفضل من عدم وجود توطين على الإطلاق.

كيف تتعامل واجهة برمجة التطبيقات Intl مع الانتقال الاحتياطي تلقائيًا

يقبل كل منشئ 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));
// يستخدم fr-CA إذا كانت متوفرة
// ينتقل احتياطيًا إلى fr-FR إذا كانت fr-CA غير متوفرة
// ينتقل احتياطيًا إلى en-US إذا لم يكن أي من متغيرات الفرنسية متوفرًا

يفحص وقت التشغيل المصفوفة من اليسار إلى اليمين. إذا كان يدعم الفرنسية الكندية، فإنه يستخدمها. إذا لم يكن كذلك، فإنه يحاول الفرنسية الأوروبية. إذا لم يكن أي من متغيرات الفرنسية متوفرًا، فإنه ينتقل احتياطيًا إلى الإنجليزية الأمريكية.

يعني هذا الانتقال الاحتياطي التلقائي أنك لا تحتاج إلى التحقق من الدعم يدويًا أو التعامل مع الأخطاء عند طلب لغات محلية محددة. تضمن واجهة برمجة التطبيقات Intl أنها ستختار لغة محلية مدعومة أو تنتقل احتياطيًا إلى الإعداد الافتراضي للنظام.

توفير خيارات متعددة للغات المحلية

الطريقة الأبسط لتنفيذ الاحتياطي هي تمرير مصفوفة من اللغات المحلية بترتيب الأفضلية. يعمل هذا مع جميع منشئات 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));
// يستخدم الإسبانية المكسيكية إذا كانت متاحة
// يرجع إلى الإسبانية الأوروبية
// يرجع إلى الإسبانية العامة
// يرجع إلى الإنجليزية كخيار نهائي

يوفر هذا النمط مسارًا سلسًا للتدرج. يحصل المستخدمون على المحتوى بلهجتهم المفضلة إذا كانت متاحة، ثم بنسخة أوسع من لغتهم، ثم بلغة احتياطية شائعة.

الترتيب مهم. يختار وقت التشغيل أول لغة محلية يدعمها، لذا ضع اللغات المحلية الأكثر تحديدًا والمفضلة أولاً.

فهم كيفية عمل مطابقة اللغة المحلية

عندما توفر لغات محلية متعددة، يستخدم وقت تشغيل جافا سكريبت خوارزمية مطابقة اللغة المحلية لاختيار أفضل خيار متاح. تقارن هذه الخوارزمية اللغات المحلية المطلوبة مع مجموعة اللغات المحلية التي يدعمها وقت التشغيل.

إذا كانت اللغة المحلية المطلوبة تطابق بالضبط لغة محلية مدعومة، فسيستخدمها وقت التشغيل على الفور. إذا لم يكن هناك تطابق دقيق، فقد يختار وقت التشغيل لغة محلية ذات صلة بناءً على رموز اللغة والمنطقة.

على سبيل المثال، إذا طلبت 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);
// قد يظهر "en-US" أو "en-GB" اعتمادًا على وقت التشغيل
// اختار وقت التشغيل متغيرًا إنجليزيًا مدعومًا

تعيد طريقة resolvedOptions() اللغة المحلية الفعلية التي يستخدمها المنسق. هذا يتيح لك التحقق من اللغة المحلية التي تم اختيارها بعد الرجوع الاحتياطي.

التحقق من اللغات المدعومة

تقوم الطريقة الثابتة supportedLocalesOf() بالتحقق من اللغات المدعومة من قائمة معينة بواسطة منشئ Intl محدد. تُرجع هذه الطريقة مصفوفة تحتوي فقط على اللغات المدعومة.

const requestedLocales = ["fr-CA", "fr-FR", "de-DE", "ja-JP"];
const supportedLocales = Intl.DateTimeFormat.supportedLocalesOf(requestedLocales);

console.log(supportedLocales);
// النتيجة تعتمد على دعم بيئة التشغيل
// مثال: ["fr-FR", "de-DE", "ja-JP"]
// الفرنسية الكندية غير مدعومة، بينما اللغات الأخرى مدعومة

تقوم هذه الطريقة بتصفية اللغات المطلوبة لإظهار اللغات التي يمكن لبيئة التشغيل استخدامها دون الرجوع إلى الإعدادات الافتراضية. يتم إزالة اللغات غير المدعومة من المصفوفة المُرجعة.

يمكنك استخدام هذه الطريقة للتحقق من الدعم قبل إنشاء المنسقات، أو لعرض خيارات اللغة المتاحة للمستخدمين.

const availableLocales = ["en-US", "es-MX", "fr-FR", "de-DE", "ja-JP"];
const supported = Intl.NumberFormat.supportedLocalesOf(availableLocales);

console.log("بيئة التشغيل هذه تدعم:", supported);
// تُظهر أي من لغات تطبيقك تعمل في هذه البيئة

كل منشئ من منشئات 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);
// يحاول استخدام الصينية المبسطة للصين
// يرجع إلى الصينية العامة
// يرجع إلى الإنجليزية

تقوم هذه الدالة بإنشاء سلسلة احتياط عن طريق استخراج رمز اللغة من معرف اللغة وإضافة احتياط نهائي باللغة الإنجليزية. يمكنك توسيع هذا المنطق ليشمل قواعد احتياط أكثر تعقيدًا بناءً على اللغات المدعومة في تطبيقك.

بالنسبة للتطبيقات التي تدعم متغيرات متعددة من لغة ما، قد ترغب في الرجوع إلى اللهجات ذات الصلة قبل الانتقال إلى الإنجليزية.

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"]
// يحاول استخدام الإسبانية الأرجنتينية
// يرجع إلى الإسبانية المكسيكية
// يرجع إلى الإسبانية الأوروبية
// يرجع إلى الإسبانية العامة
// يرجع إلى الإنجليزية

يضمن هذا النهج أن يرى المستخدمون المحتوى بلهجة ذات صلة بلغتهم قبل الرجوع إلى اللغة الإنجليزية.

اختيار خوارزمية مطابقة اللغة المحلية

تدعم واجهة برمجة التطبيقات Intl خوارزميتين لمطابقة اللغة المحلية: البحث والأفضل ملاءمة. يمكنك تحديد الخوارزمية التي تريد استخدامها من خلال خيار localeMatcher عند إنشاء المنسقات.

تتبع خوارزمية البحث مواصفات البحث BCP 47. تقوم بإجراء مطابقة صارمة من خلال مقارنة معرفات اللغة المحلية بشكل منهجي واختيار أول تطابق دقيق.

const locales = ["de-DE", "en-US"];
const formatter = new Intl.NumberFormat(locales, {
  localeMatcher: "lookup"
});

console.log(formatter.resolvedOptions().locale);
// يستخدم قواعد مطابقة البحث الصارمة

تسمح خوارزمية الأفضل ملاءمة لبيئة التشغيل باختيار لغة محلية باستخدام منطق المطابقة الخاص بها. يمكن لهذه الخوارزمية اتخاذ قرارات ذكية حول اللغة المحلية التي تخدم احتياجات المستخدم بشكل أفضل، حتى لو لم تكن مطابقة تماماً.

const locales = ["de-DE", "en-US"];
const formatter = new Intl.NumberFormat(locales, {
  localeMatcher: "best fit"
});

console.log(formatter.resolvedOptions().locale);
// يستخدم خوارزمية الأفضل ملاءمة لبيئة التشغيل
// قد يختار لغة محلية ذات صلة بشكل أكثر ذكاءً

الخوارزمية الافتراضية هي الأفضل ملاءمة. يجب على معظم التطبيقات استخدام الإعداد الافتراضي لأنه يوفر نتائج أفضل عبر بيئات تشغيل جافا سكريبت المختلفة. استخدم البحث فقط عندما تحتاج إلى سلوك مطابقة صارم ومتوقع.

استخدام تفضيلات لغة المتصفح للرجوع التلقائي

تُرجع خاصية navigator.languages مصفوفة باللغات المفضلة للمستخدم حسب ترتيب التفضيل. يمكنك تمرير هذه المصفوفة مباشرة إلى منشئات Intl لتنفيذ الرجوع التلقائي بناءً على إعدادات المتصفح.

const formatter = new Intl.DateTimeFormat(navigator.languages);

const date = new Date("2025-03-15");
console.log(formatter.format(date));
// يستخدم تلقائياً اللغة المدعومة المفضلة للمستخدم

يتيح هذا النهج للمتصفح التعامل مع كل منطق الرجوع. إذا لم يتم دعم التفضيل الأول للمستخدم، فإن واجهة برمجة التطبيقات 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));
// يجرب الفرنسية الكندية أولاً
// يرجع عبر قائمة تفضيلات المستخدم الكاملة

تقوم واجهة برمجة التطبيقات Intl بتقييم كل لغة في المصفوفة واختيار أول لغة تدعمها، مما يجعل هذا حلاً قوياً للتعامل مع تفضيلات المستخدم المتنوعة.

الجمع بين دعم التطبيق وتفضيلات المستخدم

بالنسبة للتطبيقات ذات الدعم المحدود للغات، يمكنك تصفية تفضيلات المستخدم لتتطابق مع اللغات المدعومة قبل إنشاء المنسقات. هذا يضمن أنك تحاول فقط استخدام اللغات التي يمكن لتطبيقك التعامل معها.

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);
// اللغة المحددة تتطابق مع كل من تفضيلات المستخدم ودعم التطبيق

تجد هذه الدالة أول تطابق بين تفضيلات المستخدم واللغات المدعومة، بما في ذلك محاولة استخدام رموز اللغة بدون رموز المنطقة للمطابقة الأوسع.

للمطابقة الأكثر تطوراً، يمكنك التحقق من أي من تفضيلات المستخدم مدعومة بواسطة واجهة برمجة التطبيقات Intl في بيئة التشغيل هذه.

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);

يضمن هذا النهج أن اللغة المحددة مدعومة من قبل كل من تطبيقك وبيئة تشغيل جافا سكريبت.

التعامل مع الحالات التي لا تتطابق فيها أي لغة

إذا لم تكن أي من اللغات المطلوبة مدعومة، فإن واجهة برمجة التطبيقات Intl ترجع إلى اللغة الافتراضية للنظام. تختلف هذه القيمة الافتراضية حسب البيئة ويتم تحديدها بواسطة نظام التشغيل أو المتصفح أو تكوين Node.js.

const unsupportedLocales = ["non-existent-locale"];
const formatter = new Intl.DateTimeFormat(unsupportedLocales);

console.log(formatter.resolvedOptions().locale);
// تظهر اللغة الافتراضية للنظام
// قد تكون "en-US" أو لغة أخرى اعتماداً على النظام

تضمن اللغة الافتراضية للنظام أن المنسقات تعمل دائماً، حتى مع قوائم اللغات غير الصالحة تماماً أو غير المدعومة. لن يطرح تطبيقك أخطاء بسبب مشكلات اللغة.

لضمان استخدام لغة احتياطية محددة بدلاً من الاعتماد على الإعداد الافتراضي للنظام، قم دائماً بتضمين لغة مدعومة على نطاق واسع مثل en أو en-US في نهاية مصفوفة اللغات الخاصة بك.

const locales = ["xyz-INVALID", "en"];
const formatter = new Intl.DateTimeFormat(locales);

console.log(formatter.resolvedOptions().locale);
// سيستخدم "en" لأن اللغة الأولى غير صالحة
// ضمان الرجوع إلى اللغة الإنجليزية بدلاً من الإعداد الافتراضي للنظام

يجعل هذا النمط سلوك تطبيقك أكثر قابلية للتنبؤ عبر البيئات المختلفة.

أنماط عملية للتطبيقات الإنتاجية

عند بناء تطبيقات إنتاجية، يمكن دمج استراتيجيات احتياطية متعددة لضمان معالجة قوية للغات عبر قواعد المستخدمين المتنوعة.

النمط الشائع ينشئ منسقات مع سلسلة احتياطية كاملة تتضمن تفضيلات المستخدم، واللغات المدعومة في التطبيق، واحتياطي نهائي مضمون.

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);
// يستخدم سلسلة احتياطية شاملة
// يحاول البرتغالية للبرازيل
// يعود احتياطيًا إلى البرتغالية
// يعود احتياطيًا عبر navigator.languages
// يعود احتياطيًا عبر اللغات المدعومة
// مضمون استخدام en-US إذا لم يتطابق شيء آخر

تغلف هذه الفئة منطق الاحتياط اللغوي وتضمن سلوكًا متسقًا عبر تطبيقك.

بالنسبة للتطبيقات التي تحتاج إلى الاستجابة لتغييرات لغة المستخدم في وقت التشغيل، يمكن دمج مدير اللغة مع مستمعي الأحداث.

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()));
// يتحدث تلقائيًا عندما يغير المستخدم تفضيلات اللغة

ينشئ هذا النمط منسقات تبقى متزامنة مع تغييرات لغة المتصفح، مما يضمن أن تطبيقك يعرض دائمًا المحتوى وفقًا للتفضيلات الحالية.

الملخص

يضمن الرجوع الاحتياطي للغة المحلية أن يعرض تطبيقك محتوى منسقًا بشكل صحيح حتى عندما يفضل المستخدمون لغات محلية لا تدعمها صراحةً. تتعامل واجهة برمجة التطبيقات Intl مع الرجوع الاحتياطي تلقائيًا من خلال قبول مصفوفات تفضيلات اللغة المحلية واختيار الخيار المدعوم الأول.

المفاهيم الرئيسية:

  • قم بتمرير مصفوفات اللغات المحلية إلى منشئات Intl للرجوع الاحتياطي التلقائي
  • يختار وقت التشغيل اللغة المحلية الأولى التي يدعمها من المصفوفة
  • استخدم supportedLocalesOf() للتحقق من اللغات المحلية المتاحة
  • بناء سلاسل الرجوع الاحتياطي التي تتقدم من اللغات المحلية المحددة إلى العامة
  • يتحكم خيار localeMatcher في خوارزمية المطابقة
  • قم بتمرير navigator.languages مباشرة للتعامل التلقائي مع تفضيلات المستخدم
  • قم دائمًا بتضمين لغة احتياطية نهائية مدعومة على نطاق واسع مثل الإنجليزية
  • يرجع وقت التشغيل إلى الإعدادات الافتراضية للنظام عندما لا تتطابق أي لغات محلية

استخدم الرجوع الاحتياطي التلقائي مع مصفوفات اللغة المحلية لمعظم التطبيقات. قم بتنفيذ منطق الرجوع الاحتياطي المخصص عندما تحتاج إلى تحكم محدد في اللغات المحلية التي يتم محاولة استخدامها وبأي ترتيب.