واجهة برمجة التطبيقات Intl.Locale

تحليل ومعالجة والاستعلام عن معرّفات اللغة باستخدام كائنات JavaScript منظمة

مقدمة

عند بناء تطبيقات لعدة لغات ومناطق، ستواجه معرّفات لغة مثل en-US وfr-FR أو zh-Hans-CN. تظهر هذه السلاسل النصية في واجهات برمجة تطبيقات المتصفح ورؤوس HTTP وتفضيلات المستخدم. وهي تشفّر معلومات حول اللغة والمنطقة ونظام الكتابة وتفضيلات التنسيق.

تحوّل واجهة برمجة التطبيقات Intl.Locale هذه السلاسل النصية غير الواضحة إلى كائنات منظمة يمكنك فحصها ومعالجتها. بدلاً من تحليل السلاسل النصية يدوياً أو تخمين معنى zh-Hans-CN، يمكنك إنشاء كائن لغة وقراءة خصائصه مباشرة.

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

فهم معرّفات اللغة

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

يتبع الهيكل الأكثر شيوعاً معيار BCP 47:

language-script-region-variant-extensions

كل مكون اختياري باستثناء رمز اللغة.

رموز اللغة

تستخدم رموز اللغة حرفين أو ثلاثة أحرف من ISO 639. أمثلة شائعة:

  • en للإنجليزية
  • es للإسبانية
  • fr للفرنسية
  • de للألمانية
  • ja لليابانية
  • zh للصينية
  • ar للعربية

رمز اللغة دائماً بأحرف صغيرة ويظهر أولاً في المعرّف.

رموز المنطقة

تحدد رموز المنطقة المناطق الجغرافية باستخدام حرفين كبيرين من ISO 3166-1. وهي تشير إلى أي متغير من اللغة يجب استخدامه:

  • en-US للإنجليزية الأمريكية
  • en-GB للإنجليزية البريطانية
  • es-ES للإسبانية الأوروبية
  • es-MX للإسبانية المكسيكية
  • fr-FR للفرنسية كما يتم التحدث بها في فرنسا
  • fr-CA للفرنسية الكندية

تغير رموز المناطق اصطلاحات التنسيق. تستخدم الإنجليزية الأمريكية تواريخ MM/DD/YYYY، بينما تستخدم الإنجليزية البريطانية DD/MM/YYYY.

رموز الكتابة

تحدد رموز الكتابة نظام الكتابة باستخدام أربعة أحرف مع كتابة الحرف الأول بحرف كبير. وهي مهمة للغات المكتوبة بأنظمة كتابة متعددة:

  • zh-Hans للأحرف الصينية المبسطة
  • zh-Hant للأحرف الصينية التقليدية
  • sr-Cyrl للصربية بالأحرف السيريلية
  • sr-Latn للصربية بالأحرف اللاتينية

تحذف معظم اللغات المحلية رمز الكتابة لأن اللغة تشير ضمنياً إلى نظام كتابة افتراضي. تستخدم الإنجليزية الأحرف اللاتينية بشكل افتراضي، لذلك تكتب en بدلاً من en-Latn.

علامات الامتداد

تضيف علامات الامتداد تفضيلات التنسيق إلى معرفات اللغة المحلية. تبدأ بـ -u- متبوعة بأزواج مفتاح-قيمة:

en-US-u-ca-gregory-nu-latn-hc-h12

مفاتيح الامتداد الشائعة:

  • ca لنظام التقويم (gregory، buddhist، islamic)
  • nu لنظام الترقيم (latn، arab، hanidec)
  • hc لدورة الساعة (h12، h23، h11، h24)

تخصص الامتدادات كيفية عرض المنسقات للبيانات دون تغيير اللغة أو المنطقة.

إنشاء كائنات اللغة المحلية

يقبل منشئ Intl.Locale سلسلة معرف لغة محلية ويعيد كائناً منظماً:

const locale = new Intl.Locale("en-US");

console.log(locale.language); // "en"
console.log(locale.region); // "US"

يمكنك أيضًا تمرير كائن خيارات لتجاوز الخصائص أو إضافتها:

const locale = new Intl.Locale("en", {
  region: "GB",
  hourCycle: "h23"
});

console.log(locale.baseName); // "en-GB"
console.log(locale.hourCycle); // "h23"

يطرح المُنشئ RangeError إذا كان المُعرّف غير صالح:

try {
  const invalid = new Intl.Locale("invalid-locale-code");
} catch (error) {
  console.error(error.message); // "invalid language subtag: invalid"
}

يضمن هذا التحقق اكتشاف مُعرّفات اللغة المشوهة قبل تمريرها إلى المُنسّقات.

قراءة خصائص اللغة

تعرض كائنات اللغة خصائص تتوافق مع مكونات سلسلة المُعرّف. جميع الخصائص للقراءة فقط.

الخصائص الأساسية

تُرجع الخاصية language رمز اللغة:

const locale = new Intl.Locale("fr-CA");
console.log(locale.language); // "fr"

تُرجع الخاصية region رمز المنطقة:

const locale = new Intl.Locale("fr-CA");
console.log(locale.region); // "CA"

تُرجع الخاصية script رمز الكتابة إذا كان موجودًا:

const locale = new Intl.Locale("zh-Hans-CN");
console.log(locale.script); // "Hans"

تُرجع الخاصية baseName المُعرّف الأساسي الكامل بدون الامتدادات:

const locale = new Intl.Locale("en-US-u-ca-gregory-nu-latn");
console.log(locale.baseName); // "en-US"

استخدم baseName عندما تحتاج إلى اللغة والمنطقة ولكنك تريد تجاهل تفضيلات التنسيق.

خصائص الامتداد

تُرجع خصائص الامتداد قيمًا من علامة الامتداد -u- أو undefined إذا لم يتم تحديدها.

تُرجع الخاصية calendar نظام التقويم:

const locale = new Intl.Locale("ar-SA-u-ca-islamic");
console.log(locale.calendar); // "islamic"

تُرجع الخاصية numberingSystem نظام الترقيم:

const locale = new Intl.Locale("ar-EG-u-nu-arab");
console.log(locale.numberingSystem); // "arab"

تُرجع الخاصية hourCycle تفضيل دورة الساعة:

const locale = new Intl.Locale("en-US-u-hc-h23");
console.log(locale.hourCycle); // "h23"

تُرجع الخاصية caseFirst تفضيل حالة الأحرف في الترتيب:

const locale = new Intl.Locale("en-US-u-kf-upper");
console.log(locale.caseFirst); // "upper"

تشير الخاصية numeric إلى ما إذا كان الترتيب الرقمي مُفعّلاً:

const locale = new Intl.Locale("en-US-u-kn-true");
console.log(locale.numeric); // true

تتيح لك هذه الخاصيات فحص تفضيلات التنسيق دون تحليل سلسلة الامتداد يدوياً.

الاستعلام عن معلومات اللغة المحلية

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

التقاويم المتاحة

تُرجع الدالة getCalendars() أنظمة التقويم الشائعة الاستخدام للغة المحلية:

const locale = new Intl.Locale("th-TH");
const calendars = locale.getCalendars();
console.log(calendars); // ["buddhist", "gregory"]

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

ترتيبات الفرز المتاحة

تُرجع الدالة getCollations() أنواع الترتيب لفرز السلاسل النصية:

const locale = new Intl.Locale("de-DE");
const collations = locale.getCollations();
console.log(collations); // ["phonebk", "emoji", "eor"]

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

دورات الساعة المتاحة

تُرجع الدالة getHourCycles() تنسيقات دورة الساعة:

const locale = new Intl.Locale("en-US");
const hourCycles = locale.getHourCycles();
console.log(hourCycles); // ["h12"]

تستخدم الإنجليزية الأمريكية نظام 12 ساعة افتراضياً. تُرجع العديد من اللغات المحلية الأخرى ["h23"] لنظام 24 ساعة.

أنظمة الترقيم المتاحة

تُرجع الدالة getNumberingSystems() أنظمة الترقيم الشائعة الاستخدام للغة المحلية:

const locale = new Intl.Locale("ar-EG");
const numberingSystems = locale.getNumberingSystems();
console.log(numberingSystems); // ["arab", "latn"]

تدعم اللغات المحلية العربية غالباً كلاً من الأرقام العربية الهندية والأرقام اللاتينية.

اتجاه النص

تُرجع الدالة getTextInfo() معلومات ترتيب النص:

const locale = new Intl.Locale("ar-SA");
const textInfo = locale.getTextInfo();
console.log(textInfo.direction); // "rtl"

اللغات التي تُكتب من اليمين إلى اليسار مثل العربية والعبرية تُرجع "rtl". اللغات التي تُكتب من اليسار إلى اليمين تُرجع "ltr".

اصطلاحات الأسبوع

تُرجع الدالة getWeekInfo() بنية الأسبوع للإعدادات المحلية:

const locale = new Intl.Locale("en-US");
const weekInfo = locale.getWeekInfo();
console.log(weekInfo.firstDay); // 7 (Sunday)
console.log(weekInfo.weekend); // [6, 7] (Saturday, Sunday)
console.log(weekInfo.minimalDays); // 1

تختلف اصطلاحات الأسبوع حسب المنطقة. تبدأ الأسابيع الأمريكية يوم الأحد، بينما تبدأ معظم الأسابيع الأوروبية يوم الاثنين.

المناطق الزمنية

تُرجع الدالة getTimeZones() المناطق الزمنية لمنطقة الإعدادات المحلية:

const locale = new Intl.Locale("en-US");
const timeZones = locale.getTimeZones();
console.log(timeZones); // ["America/New_York", "America/Chicago", ...]

تُرجع هذه الدالة معرّفات المناطق الزمنية وفقًا لـ IANA لرمز المنطقة.

تعظيم معرّفات الإعدادات المحلية

تضيف الدالة maximize() علامات فرعية محتملة لإنشاء معرّف كامل. تستنتج رموز النص والمنطقة المفقودة بناءً على بيانات اللغة.

عندما تحدد رمز اللغة فقط، تضيف maximize() النص والمنطقة الأكثر شيوعًا:

const locale = new Intl.Locale("en");
const maximized = locale.maximize();
console.log(maximized.baseName); // "en-Latn-US"

تُعيّن اللغة الإنجليزية افتراضيًا إلى النص اللاتيني ومنطقة الولايات المتحدة لأنهما الارتباطات الأكثر شيوعًا.

يعتمد تعظيم اللغة الصينية على النص:

const simplified = new Intl.Locale("zh-Hans");
const maximized = simplified.maximize();
console.log(maximized.baseName); // "zh-Hans-CN"

const traditional = new Intl.Locale("zh-Hant");
const maximizedTrad = traditional.maximize();
console.log(maximizedTrad.baseName); // "zh-Hant-TW"

ترتبط الصينية المبسطة بالصين، بينما ترتبط الصينية التقليدية بتايوان.

استخدم maximize() عند تطبيع إدخال المستخدم أو مقارنة معرّفات الإعدادات المحلية. تجعل المعلومات الضمنية صريحة.

تصغير معرّفات الإعدادات المحلية

تزيل الدالة minimize() العلامات الفرعية الزائدة لإنشاء أقصر معرّف مكافئ. تزيل رموز النص والمنطقة عندما تطابق الإعدادات الافتراضية المحتملة.

عندما تستخدم الإعدادات المحلية النص والمنطقة الافتراضيين، تزيلهما minimize():

const locale = new Intl.Locale("en-Latn-US");
const minimized = locale.minimize();
console.log(minimized.baseName); // "en"

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

بالنسبة للغات المحلية ذات المناطق غير الافتراضية، يحتفظ minimize() بالمنطقة:

const locale = new Intl.Locale("en-Latn-GB");
const minimized = locale.minimize();
console.log(minimized.baseName); // "en-GB"

تحتاج الإنجليزية البريطانية إلى رمز المنطقة لأنها تختلف عن الافتراضية.

استخدم minimize() لإنشاء معرفات مدمجة للتخزين أو عناوين URL مع الحفاظ على المعنى.

التحويل إلى سلاسل نصية

تُرجع الدالة toString() معرف اللغة المحلية الكامل بما في ذلك الامتدادات:

const locale = new Intl.Locale("en-US", {
  calendar: "gregory",
  numberingSystem: "latn",
  hourCycle: "h12"
});

console.log(locale.toString()); // "en-US-u-ca-gregory-hc-h12-nu-latn"

التمثيل النصي صالح لتمريره إلى واجهات برمجة التطبيقات الأخرى لـ Intl أو تخزينه كبيانات تكوين.

يمكنك أيضًا تحويل كائنات اللغة المحلية إلى سلاسل نصية بشكل ضمني:

const locale = new Intl.Locale("fr-FR");
const formatter = new Intl.DateTimeFormat(locale);

يقبل المُنشئ DateTimeFormat كائنات اللغة المحلية مباشرة ويستدعي toString() داخليًا.

حالات الاستخدام العملية

تحل واجهة برمجة التطبيقات Intl.Locale العديد من المشكلات الشائعة عند بناء تطبيقات متعددة اللغات.

بناء محددات اللغة المحلية

تتيح محددات اللغة المحلية للمستخدمين اختيار لغتهم ومنطقتهم. تساعد واجهة برمجة التطبيقات Intl.Locale في تحليل اختيارات المستخدمين والتحقق من صحتها:

function createLocaleSelector(locales) {
  const options = locales.map(identifier => {
    const locale = new Intl.Locale(identifier);
    const displayName = new Intl.DisplayNames([identifier], { type: "language" });

    return {
      value: locale.toString(),
      label: displayName.of(locale.language),
      region: locale.region
    };
  });

  return options;
}

const options = createLocaleSelector(["en-US", "en-GB", "fr-FR", "es-MX"]);
console.log(options);
// [
//   { value: "en-US", label: "English", region: "US" },
//   { value: "en-GB", label: "English", region: "GB" },
//   { value: "fr-FR", label: "French", region: "FR" },
//   { value: "es-MX", label: "Spanish", region: "MX" }
// ]

التحقق من صحة إدخال اللغة المحلية

عند قبول معرفات اللغة المحلية من إدخال المستخدم أو ملفات التكوين، تحقق من صحتها قبل الاستخدام:

function validateLocale(identifier) {
  try {
    const locale = new Intl.Locale(identifier);
    return {
      valid: true,
      locale: locale.toString(),
      language: locale.language,
      region: locale.region
    };
  } catch (error) {
    return {
      valid: false,
      error: error.message
    };
  }
}

console.log(validateLocale("en-US")); // { valid: true, locale: "en-US", ... }
console.log(validateLocale("invalid")); // { valid: false, error: "..." }

استخراج اللغة للبدائل الاحتياطية

عند تنفيذ سلاسل البدائل الاحتياطية للغة، استخرج رمز اللغة بدون المنطقة:

function getLanguageFallback(identifier) {
  const locale = new Intl.Locale(identifier);
  const fallbacks = [locale.toString()];

  if (locale.region) {
    const languageOnly = new Intl.Locale(locale.language);
    fallbacks.push(languageOnly.toString());
  }

  fallbacks.push("en");

  return fallbacks;
}

console.log(getLanguageFallback("fr-CA"));
// ["fr-CA", "fr", "en"]

ينشئ هذا سلسلة بدائل احتياطية تحاول اللغة المحلية المحددة، ثم اللغة بدون منطقة، ثم اللغة الافتراضية.

تكوين أدوات التنسيق

استخدم كائنات اللغة المحلية لتكوين أدوات تنسيق Intl بتفضيلات محددة:

function createFormatter(baseLocale, options = {}) {
  const locale = new Intl.Locale(baseLocale, {
    calendar: options.calendar || "gregory",
    numberingSystem: options.numberingSystem || "latn",
    hourCycle: options.hourCycle || "h23"
  });

  return {
    date: new Intl.DateTimeFormat(locale),
    number: new Intl.NumberFormat(locale),
    locale: locale.toString()
  };
}

const formatter = createFormatter("ar-SA", {
  calendar: "islamic",
  numberingSystem: "arab"
});

console.log(formatter.locale); // "ar-SA-u-ca-islamic-nu-arab"

اكتشاف تفضيلات المستخدم

توفر واجهات برمجة تطبيقات المتصفح سلاسل نصية للغة يمكنك تحليلها لفهم تفضيلات المستخدم:

function getUserPreferences() {
  const userLocale = new Intl.Locale(navigator.language);
  const hourCycles = userLocale.getHourCycles();
  const calendars = userLocale.getCalendars();
  const textInfo = userLocale.getTextInfo();

  return {
    language: userLocale.language,
    region: userLocale.region,
    preferredHourCycle: hourCycles[0],
    preferredCalendar: calendars[0],
    textDirection: textInfo.direction
  };
}

const preferences = getUserPreferences();
console.log(preferences);
// { language: "en", region: "US", preferredHourCycle: "h12", ... }

ينشئ هذا ملفاً تعريفياً لتفضيلات المستخدم بناءً على إعدادات المتصفح الخاصة بهم.

دعم المتصفحات

تعمل واجهة برمجة التطبيقات Intl.Locale في جميع المتصفحات الحديثة. توفر Chrome وFirefox وSafari وEdge دعماً كاملاً للمُنشئ والخصائص والدوال الموضحة في هذا الدليل.

تتطلب الدوال الأحدث مثل getCalendars() وgetCollations() وgetHourCycles() وgetNumberingSystems() وgetTextInfo() وgetTimeZones() وgetWeekInfo() إصدارات حديثة من المتصفحات. تحقق من جداول توافق المتصفحات قبل استخدام هذه الدوال إذا كنت تدعم متصفحات أقدم.

يدعم Node.js واجهة برمجة التطبيقات Intl.Locale بدءاً من الإصدار 12، مع دعم كامل للدوال في الإصدار 18 وما بعده.

الملخص

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

المفاهيم الأساسية:

  • تحتوي معرفات اللغة على مكونات اللغة والنص والمنطقة والامتداد
  • يتحقق المُنشئ Intl.Locale من صحة المعرفات وينشئ الكائنات
  • توفر الخصائص مثل language وregion وcalendar وصولاً منظماً
  • تُرجع الدوال مثل getCalendars() وgetHourCycles() الخيارات المتاحة
  • تعمل دالتا maximize() وminimize() على توحيد المعرفات
  • تعمل كائنات اللغة مباشرة مع واجهات برمجة التطبيقات الأخرى Intl

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