كيفية توحيد معرفات اللغات المحلية إلى الشكل القياسي

تحويل معرفات اللغات المحلية إلى التنسيق القياسي مع الحالة الصحيحة وترتيب المكونات

مقدمة

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

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

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

ماذا يعني التطبيع لمعرفات اللغة المحلية

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

يتبع معرف اللغة المحلية المطبع هذه الاتفاقيات:

  • رموز اللغة بأحرف صغيرة
  • رموز النصوص بحالة العنوان مع الحرف الأول كبير
  • رموز المنطقة بأحرف كبيرة
  • رموز المتغيرات بأحرف صغيرة
  • كلمات الامتداد مرتبة أبجدياً
  • سمات الامتداد مرتبة أبجدياً

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

فهم قواعد التطبيع

لكل مكون من مكونات معرف اللغة المحلية اتفاقية حالة أحرف محددة في الشكل الأساسي.

حالة أحرف اللغة

تستخدم رموز اللغة دائماً أحرفاً صغيرة:

en (صحيح)
EN (غير صحيح، لكن يتم تطبيعه إلى en)
eN (غير صحيح، لكن يتم تطبيعه إلى en)

ينطبق هذا على رموز اللغة ذات الحرفين والثلاثة أحرف.

حالة أحرف النص البرمجي

تستخدم رموز النصوص البرمجية حالة العنوان، حيث يكون الحرف الأول كبيرًا والأحرف الثلاثة المتبقية صغيرة:

Hans (صحيح)
hans (غير صحيح، لكن يتم توحيده إلى Hans)
HANS (غير صحيح، لكن يتم توحيده إلى Hans)

تشمل رموز النصوص البرمجية الشائعة Latn للاتينية، وCyrl للسيريلية، وHans لأحرف هان المبسطة، وHant لأحرف هان التقليدية.

حالة أحرف المنطقة

تستخدم رموز المناطق دائمًا الأحرف الكبيرة:

US (صحيح)
us (غير صحيح، لكن يتم توحيده إلى US)
Us (غير صحيح، لكن يتم توحيده إلى US)

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

ترتيب الامتدادات

تحتوي علامات امتداد يونيكود على كلمات مفتاحية تحدد تفضيلات التنسيق. في الشكل القياسي، تظهر هذه الكلمات المفتاحية بترتيب أبجدي حسب مفتاحها:

en-US-u-ca-gregory-nu-latn (صحيح)
en-US-u-nu-latn-ca-gregory (غير صحيح، لكن يتم توحيده إلى الشكل الأول)

مفتاح التقويم ca يأتي قبل مفتاح نظام الترقيم nu أبجديًا، لذلك يظهر ca-gregory أولاً في الشكل الموحد.

استخدام Intl.getCanonicalLocales للتوحيد

تقوم طريقة Intl.getCanonicalLocales() بتوحيد معرفات اللغات المحلية وإرجاعها في شكلها القياسي. هذه هي الطريقة الأساسية للتوحيد في جافا سكريبت.

const normalized = Intl.getCanonicalLocales("EN-us");
console.log(normalized);
// ["en-US"]

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

توحيد رموز اللغات

تحول الطريقة رموز اللغات إلى أحرف صغيرة:

const result = Intl.getCanonicalLocales("FR-fr");
console.log(result);
// ["fr-FR"]

رمز اللغة FR يصبح fr في المخرجات.

توحيد رموز النصوص البرمجية

تحول الطريقة رموز النصوص البرمجية إلى حالة العنوان:

const result = Intl.getCanonicalLocales("zh-HANS-cn");
console.log(result);
// ["zh-Hans-CN"]

رمز النص البرمجي HANS يصبح Hans، ورمز المنطقة cn يصبح CN.

تطبيع رموز المناطق

تقوم الطريقة بتحويل رموز المناطق إلى أحرف كبيرة:

const result = Intl.getCanonicalLocales("en-gb");
console.log(result);
// ["en-GB"]

رمز المنطقة gb يصبح GB في المخرجات.

تطبيع كلمات الامتداد

تقوم الطريقة بترتيب كلمات الامتداد أبجديًا:

const result = Intl.getCanonicalLocales("en-US-u-nu-latn-hc-h12-ca-gregory");
console.log(result);
// ["en-US-u-ca-gregory-hc-h12-nu-latn"]

تتم إعادة ترتيب الكلمات المفتاحية من nu-latn-hc-h12-ca-gregory إلى ca-gregory-hc-h12-nu-latn لأن ca يأتي قبل hc وhc يأتي قبل nu أبجديًا.

تطبيع معرفات اللغات المتعددة

تقبل طريقة Intl.getCanonicalLocales() مصفوفة من معرفات اللغات وتقوم بتطبيع جميعها:

const locales = ["EN-us", "fr-FR", "ZH-hans-cn"];
const normalized = Intl.getCanonicalLocales(locales);
console.log(normalized);
// ["en-US", "fr-FR", "zh-Hans-CN"]

يتم تحويل كل لغة في المصفوفة إلى شكلها القياسي.

إزالة التكرارات

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

const locales = ["en-US", "EN-us", "en-us"];
const normalized = Intl.getCanonicalLocales(locales);
console.log(normalized);
// ["en-US"]

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

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

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

إذا كان أي معرف لغة في المصفوفة غير صالح، فإن الطريقة تطرح خطأ RangeError:

try {
  Intl.getCanonicalLocales(["en-US", "invalid", "fr-FR"]);
} catch (error) {
  console.error(error.message);
  // "invalid is not a structurally valid language tag"
}

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

استخدام Intl.Locale للتطبيع

يقوم منشئ Intl.Locale أيضًا بتطبيع معرفات اللغات عند إنشاء كائنات اللغة. يمكنك الوصول إلى النموذج المطبع من خلال طريقة toString().

const locale = new Intl.Locale("EN-us");
console.log(locale.toString());
// "en-US"

يقبل المنشئ أي حالة صالحة للأحرف وينتج كائن لغة مطبع.

الوصول إلى المكونات المعيارية

تُرجع كل خاصية من كائن اللغة المحلية الشكل المعياري لذلك المكون:

const locale = new Intl.Locale("ZH-hans-CN");

console.log(locale.language);
// "zh"

console.log(locale.script);
// "Hans"

console.log(locale.region);
// "CN"

console.log(locale.baseName);
// "zh-Hans-CN"

تستخدم خصائص language وscript وregion جميعها حالة الأحرف الصحيحة للشكل القانوني.

التعيير باستخدام الخيارات

عند إنشاء كائن لغة محلية مع خيارات، يقوم المُنشئ بتعيير كل من المعرف الأساسي والخيارات:

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"

تظهر كلمات امتداد المفاتيح بترتيب أبجدي في المخرجات، على الرغم من أن كائن الخيارات لا يحدد أي ترتيب معين.

لماذا التعيير مهم

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

تخزين متسق

عند تخزين معرفات اللغة المحلية في قواعد البيانات أو ملفات التكوين أو التخزين المحلي، تمنع الأشكال المعيارية التكرار:

const userPreferences = new Set();

function saveUserLocale(identifier) {
  const normalized = Intl.getCanonicalLocales(identifier)[0];
  userPreferences.add(normalized);
}

saveUserLocale("en-US");
saveUserLocale("EN-us");
saveUserLocale("en-us");

console.log(userPreferences);
// Set { "en-US" }

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

مقارنة موثوقة

تتطلب مقارنة معرفات اللغة المحلية التعيير. معرفان يختلفان فقط في حالة الأحرف يمثلان نفس اللغة المحلية:

function isSameLocale(locale1, locale2) {
  const normalized1 = Intl.getCanonicalLocales(locale1)[0];
  const normalized2 = Intl.getCanonicalLocales(locale2)[0];
  return normalized1 === normalized2;
}

console.log(isSameLocale("en-US", "EN-us"));
// true

console.log(isSameLocale("en-US", "en-GB"));
// false

المقارنة المباشرة للسلاسل النصية للمعرفات غير المعيارية تنتج نتائج غير صحيحة.

عرض متسق

عند عرض معرفات اللغات المحلية للمستخدمين أو في مخرجات التصحيح، توفر الأشكال المعيارية تنسيقًا متسقًا:

function displayLocale(identifier) {
  try {
    const normalized = Intl.getCanonicalLocales(identifier)[0];
    return `Current locale: ${normalized}`;
  } catch (error) {
    return "Invalid locale identifier";
  }
}

console.log(displayLocale("EN-us"));
// "Current locale: en-US"

console.log(displayLocale("zh-HANS-cn"));
// "Current locale: zh-Hans-CN"

يرى المستخدمون معرفات اللغات المحلية المنسقة بشكل صحيح بغض النظر عن تنسيق الإدخال.

التطبيقات العملية

تحل المعايرة المشكلات الشائعة عند العمل مع معرفات اللغات المحلية في التطبيقات الحقيقية.

معايرة إدخال المستخدم

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

function processLocaleInput(input) {
  try {
    const normalized = Intl.getCanonicalLocales(input)[0];
    return {
      success: true,
      locale: normalized
    };
  } catch (error) {
    return {
      success: false,
      error: "Please enter a valid locale identifier"
    };
  }
}

const result = processLocaleInput("fr-ca");
console.log(result);
// { success: true, locale: "fr-CA" }

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

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

عند إنشاء جداول بحث للترجمات أو البيانات الخاصة باللغات المحلية، استخدم مفاتيح معيارية:

const translations = new Map();

function addTranslation(locale, key, value) {
  const normalized = Intl.getCanonicalLocales(locale)[0];

  if (!translations.has(normalized)) {
    translations.set(normalized, {});
  }

  translations.get(normalized)[key] = value;
}

addTranslation("en-us", "hello", "Hello");
addTranslation("EN-US", "goodbye", "Goodbye");

console.log(translations.get("en-US"));
// { hello: "Hello", goodbye: "Goodbye" }

كلا الاستدعاءين لـ addTranslation يستخدمان نفس المفتاح المعياري، لذلك يتم تخزين الترجمات في نفس الكائن.

دمج قوائم اللغات المحلية

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

function mergeLocales(...sources) {
  const allLocales = sources.flat();
  const normalized = Intl.getCanonicalLocales(allLocales);
  return normalized;
}

const userLocales = ["en-us", "fr-FR"];
const appLocales = ["EN-US", "de-de"];
const systemLocales = ["en-US", "es-mx"];

const merged = mergeLocales(userLocales, appLocales, systemLocales);
console.log(merged);
// ["en-US", "fr-FR", "de-DE", "es-MX"]

تزيل الطريقة التكرارات وتعاير حالة الأحرف عبر جميع المصادر.

إنشاء واجهات اختيار اللغة

عند بناء القوائم المنسدلة أو واجهات الاختيار، قم بتوحيد معرّفات اللغة للعرض:

function buildLocaleOptions(locales) {
  const normalized = Intl.getCanonicalLocales(locales);

  return normalized.map(locale => {
    const localeObj = new Intl.Locale(locale);
    const displayNames = new Intl.DisplayNames([locale], {
      type: "language"
    });

    return {
      value: locale,
      label: displayNames.of(localeObj.language)
    };
  });
}

const options = buildLocaleOptions(["EN-us", "fr-FR", "DE-de"]);
console.log(options);
// [
//   { value: "en-US", label: "English" },
//   { value: "fr-FR", label: "French" },
//   { value: "de-DE", label: "German" }
// ]

توفر القيم الموحدة معرّفات متسقة لتقديم النماذج.

التحقق من صحة ملفات التكوين

عند تحميل معرّفات اللغة من ملفات التكوين، قم بتوحيدها أثناء التهيئة:

function loadLocaleConfig(config) {
  const validatedConfig = {
    defaultLocale: null,
    supportedLocales: []
  };

  try {
    validatedConfig.defaultLocale = Intl.getCanonicalLocales(
      config.defaultLocale
    )[0];
  } catch (error) {
    console.error("Invalid default locale:", config.defaultLocale);
    validatedConfig.defaultLocale = "en-US";
  }

  config.supportedLocales.forEach(locale => {
    try {
      const normalized = Intl.getCanonicalLocales(locale)[0];
      validatedConfig.supportedLocales.push(normalized);
    } catch (error) {
      console.warn("Skipping invalid locale:", locale);
    }
  });

  return validatedConfig;
}

const config = {
  defaultLocale: "en-us",
  supportedLocales: ["EN-us", "fr-FR", "invalid", "de-DE"]
};

const validated = loadLocaleConfig(config);
console.log(validated);
// {
//   defaultLocale: "en-US",
//   supportedLocales: ["en-US", "fr-FR", "de-DE"]
// }

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

التوحيد ومطابقة اللغة

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

function findBestMatch(userPreference, availableLocales) {
  const normalizedPreference = Intl.getCanonicalLocales(userPreference)[0];
  const normalizedAvailable = Intl.getCanonicalLocales(availableLocales);

  if (normalizedAvailable.includes(normalizedPreference)) {
    return normalizedPreference;
  }

  const preferenceLocale = new Intl.Locale(normalizedPreference);

  const languageMatch = normalizedAvailable.find(available => {
    const availableLocale = new Intl.Locale(available);
    return availableLocale.language === preferenceLocale.language;
  });

  if (languageMatch) {
    return languageMatch;
  }

  return normalizedAvailable[0];
}

const available = ["en-us", "fr-FR", "DE-de"];
console.log(findBestMatch("EN-GB", available));
// "en-US"

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

التطبيع لا يغير المعنى

التطبيع يؤثر فقط على تمثيل معرّف اللغة المحلية. لا يغير اللغة أو النص أو المنطقة التي يمثلها المعرّف.

const locale1 = new Intl.Locale("en-us");
const locale2 = new Intl.Locale("EN-US");

console.log(locale1.language === locale2.language);
// true

console.log(locale1.region === locale2.region);
// true

console.log(locale1.toString() === locale2.toString());
// true

كلا المعرّفين يشيران إلى الإنجليزية الأمريكية. التطبيع يضمن ببساطة أنهما يُكتبان بنفس الطريقة.

هذا يختلف عن العمليات مثل maximize() و minimize()، التي تضيف أو تزيل المكونات ويمكن أن تغير خصوصية المعرّف.

دعم المتصفح

طريقة Intl.getCanonicalLocales() تعمل في جميع المتصفحات الحديثة. كروم وفايرفوكس وسفاري وإيدج توفر دعمًا كاملًا.

Node.js يدعم Intl.getCanonicalLocales() بدءًا من الإصدار 9، مع دعم كامل في الإصدار 10 وما بعده.

منشئ Intl.Locale وسلوك التطبيع الخاص به يعملان في جميع المتصفحات التي تدعم واجهة برمجة تطبيقات Intl.Locale. وهذا يشمل الإصدارات الحديثة من كروم وفايرفوكس وسفاري وإيدج.

الملخص

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

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

  • الشكل القانوني يستخدم الأحرف الصغيرة للغات، وحالة العنوان للنصوص، والأحرف الكبيرة للمناطق
  • يتم ترتيب كلمات الامتداد أبجديًا في الشكل القانوني
  • طريقة Intl.getCanonicalLocales() تطبّع المعرّفات وتزيل التكرارات
  • منشئ Intl.Locale ينتج أيضًا مخرجات مطبّعة
  • التطبيع لا يغير معنى معرّف اللغة المحلية
  • استخدم المعرّفات المطبّعة للتخزين والمقارنة والعرض

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