كيفية تحويل النص إلى أحرف كبيرة أو صغيرة وفقًا لقواعد اللغة
استخدم JavaScript لتغيير حالة النص بشكل صحيح للغات وأنظمة الكتابة المختلفة
مقدمة
عندما تقوم بتحويل النص بين الأحرف الكبيرة والصغيرة، قد تفترض أن هذه العملية تعمل بنفس الطريقة لجميع اللغات. لكن الأمر ليس كذلك. تتبع أنظمة الكتابة المختلفة قواعد مختلفة لتحويل حالة الأحرف، ويمكن أن تنتج هذه القواعد نتائج غير متوقعة إذا لم تأخذها في الاعتبار.
توفر JavaScript الدوال القياسية toUpperCase() و toLowerCase()، والتي تعمل بشكل صحيح للغة الإنجليزية ولكن يمكن أن تنتج نتائج غير صحيحة للغات أخرى. تطبق الدوال الواعية للغة toLocaleUpperCase() و toLocaleLowerCase() قواعد تحويل حالة الأحرف الخاصة باللغة، مما يضمن تحويل النص بشكل صحيح بغض النظر عن اللغة.
يشرح هذا الدرس سبب اختلاف تحويل حالة الأحرف عبر اللغات، ويوضح المشكلات المحددة التي تنشأ مع الدوال القياسية، ويوضح كيفية استخدام الدوال الواعية للغة للتعامل مع تحويل حالة الأحرف بشكل صحيح للتطبيقات الدولية.
لماذا يختلف تحويل حالة الأحرف حسب اللغة
الإصدارات الكبيرة والصغيرة من الأحرف ليست مفاهيم عالمية تعمل بشكل متطابق عبر جميع أنظمة الكتابة. طورت اللغات المختلفة قواعد مختلفة لتحويل حالة الأحرف بناءً على اتفاقيات الكتابة التاريخية والممارسات الطباعية الخاصة بها.
في اللغة الإنجليزية، يكون تحويل حالة الأحرف واضحًا ومباشرًا. يصبح الحرف i هو I عند تحويله إلى حرف كبير، ويصبح I هو i عند تحويله إلى حرف صغير. تنطبق هذه العلاقة على الأبجدية الإنجليزية بأكملها.
اللغات الأخرى لديها قواعد أكثر تعقيدًا. تحتوي اللغة التركية على أربعة أحرف i مختلفة بدلاً من اثنين. تحتوي اللغة الألمانية على الحرف ß (s الحادة)، والذي له قواعد محددة للتحويل إلى أحرف كبيرة. تحتوي اللغة اليونانية على أشكال مختلفة من حرف سيجما اعتمادًا على ما إذا كان يظهر في نهاية الكلمة.
عند استخدام طرق JavaScript القياسية مثل toUpperCase() وtoLowerCase()، يتبع التحويل قواعد اللغة الإنجليزية. ينتج عن هذا نتائج غير صحيحة للنصوص بلغات أخرى. تطبق الطرق الواعية للغة القواعد المناسبة لكل لغة، مما يضمن التحويل الصحيح.
مشكلة حرف i التركي
توفر اللغة التركية المثال الأوضح على أهمية اللغة في تحويل الحالة. على عكس الإنجليزية، تحتوي التركية على أربعة أحرف متميزة مرتبطة بحرف i:
- حرف i الصغير المنقوط:
i(U+0069) - حرف İ الكبير المنقوط:
İ(U+0130) - حرف ı الصغير غير المنقوط:
ı(U+0131) - حرف I الكبير غير المنقوط:
I(U+0049)
في اللغة التركية، يصبح حرف i الصغير المنقوط حرف İ الكبير المنقوط. يصبح حرف ı الصغير غير المنقوط حرف I الكبير غير المنقوط. هذان زوجان منفصلان من الأحرف لهما نطق ومعاني مختلفة.
تتبع طرق JavaScript القياسية قواعد اللغة الإنجليزية وتحول حرف i المنقوط إلى حرف I غير المنقوط. يؤدي هذا إلى تغيير معنى الكلمات التركية وينتج نصاً غير صحيح.
const turkish = "istanbul";
console.log(turkish.toUpperCase());
// Output: "ISTANBUL" (incorrect - uses dotless I)
console.log(turkish.toLocaleUpperCase("tr"));
// Output: "İSTANBUL" (correct - uses dotted İ)
يحتوي اسم مدينة إسطنبول على حرف i المنقوط. عند تحويله إلى أحرف كبيرة باستخدام القواعد التركية، يصبح İSTANBUL بحرف İ منقوط. استخدام toUpperCase() القياسي ينتج ISTANBUL بحرف I غير منقوط، وهو غير صحيح في اللغة التركية.
تحدث نفس المشكلة بالعكس عند تحويل النص التركي بالأحرف الكبيرة إلى أحرف صغيرة.
const uppercase = "İSTANBUL";
console.log(uppercase.toLowerCase());
// Output: "i̇stanbul" (incorrect - creates i with combining dot above)
console.log(uppercase.toLocaleLowerCase("tr"));
// Output: "istanbul" (correct - produces dotted i)
يجب أن يصبح حرف İ المنقوط حرف i منقوطاً عند تحويله إلى أحرف صغيرة في اللغة التركية. لا تتعامل toLowerCase() القياسية مع هذا بشكل صحيح ويمكن أن تنتج حرف i صغير مع حرف نقطة مركب، والذي يبدو مشابهاً لكنه غير صحيح تقنياً.
قواعد حالة الأحرف الخاصة باللغات الأخرى
التركية ليست اللغة الوحيدة التي لديها قواعد خاصة لتحويل حالة الأحرف. تتطلب العديد من اللغات الأخرى معالجة خاصة باللغة.
تحتوي الألمانية على الحرف ß (s الحادة)، والذي لم يكن له تقليدياً شكل بالأحرف الكبيرة. في عام 2017، أضاف Unicode الحرف الكبير ẞ، لكن العديد من الأنظمة لا تزال تحول ß إلى SS عند التحويل إلى أحرف كبيرة.
const german = "Straße";
console.log(german.toUpperCase());
// Output: "STRASSE" (converts ß to SS)
console.log(german.toLocaleUpperCase("de"));
// Output: "STRASSE" (also converts ß to SS)
تنتج كلتا الطريقتين نفس النتيجة للنص الألماني في معظم بيئات JavaScript. لا يغير معامل اللغة المخرجات، لكن استخدام الطريقة الواعية باللغة يضمن بقاء الكود صحيحاً في حالة تغيير معالجة Unicode في التطبيقات المستقبلية.
تحتوي اليونانية على ثلاثة أشكال مختلفة لحرف sigma. يستخدم الشكل الصغير σ في منتصف الكلمات و ς في نهاية الكلمات. يتحول كلا الشكلين إلى نفس الحرف الكبير Σ.
تحتوي الليتوانية على قواعد خاصة للأحرف المنقوطة. يحتفظ الحرف i بنقطته عند دمجه مع علامات تشكيل معينة، حتى عند التحويل إلى أحرف كبيرة. يؤثر هذا على كيفية معالجة الطرق الواعية باللغة لتركيبات أحرف معينة.
استخدام toLocaleUpperCase للتحويل إلى أحرف كبيرة مع مراعاة اللغة
تحول طريقة toLocaleUpperCase() السلسلة النصية إلى أحرف كبيرة باستخدام قواعد تعيين حالة الأحرف الخاصة باللغة. يتم استدعاؤها على سلسلة نصية ويمكن تمرير معرف اللغة كوسيط اختياري.
const text = "istanbul";
const result = text.toLocaleUpperCase("tr");
console.log(result);
// Output: "İSTANBUL"
يحول هذا السلسلة النصية إلى أحرف كبيرة باستخدام القواعد التركية. يصبح حرف i المنقوط İ المنقوط، وهو الصحيح للتركية.
يمكنك تحويل نفس النص باستخدام قواعد لغات مختلفة.
const text = "istanbul";
console.log(text.toLocaleUpperCase("tr"));
// Output: "İSTANBUL" (Turkish rules - dotted İ)
console.log(text.toLocaleUpperCase("en"));
// Output: "ISTANBUL" (English rules - dotless I)
يحدد معامل اللغة قواعد تحويل حالة الأحرف التي يتم تطبيقها. تحافظ القواعد التركية على النقطة على حرف i، بينما لا تفعل القواعد الإنجليزية ذلك.
إذا استدعيت toLocaleUpperCase() بدون معاملات، فإنها تستخدم الإعدادات المحلية للنظام التي تحددها بيئة تشغيل JavaScript.
const text = "istanbul";
const result = text.toLocaleUpperCase();
console.log(result);
// Output depends on system locale
يعتمد الناتج على الإعدادات المحلية الافتراضية لبيئة JavaScript، والتي عادةً ما تطابق إعدادات نظام التشغيل الخاص بالمستخدم.
استخدام toLocaleLowerCase للتحويل إلى أحرف صغيرة مع مراعاة الإعدادات المحلية
تقوم الدالة toLocaleLowerCase() بتحويل السلسلة النصية إلى أحرف صغيرة باستخدام قواعد تعيين الحالة الخاصة بالإعدادات المحلية. تعمل بنفس طريقة toLocaleUpperCase() ولكنها تحول إلى أحرف صغيرة بدلاً من أحرف كبيرة.
const text = "İSTANBUL";
const result = text.toLocaleLowerCase("tr");
console.log(result);
// Output: "istanbul"
يحول هذا النص التركي بالأحرف الكبيرة إلى أحرف صغيرة باستخدام القواعد التركية. يصبح الحرف İ المنقط هو الحرف i المنقط، مما ينتج الشكل الصحيح بالأحرف الصغيرة.
بدون معامل الإعدادات المحلية، قد لا تتعامل الدالة toLowerCase() القياسية أو toLocaleLowerCase() مع إعدادات الإعدادات المحلية الافتراضية بشكل صحيح مع الأحرف التركية.
const text = "İSTANBUL";
console.log(text.toLowerCase());
// Output: "i̇stanbul" (incorrect - i with combining dot above)
console.log(text.toLocaleLowerCase("tr"));
// Output: "istanbul" (correct - dotted i)
يتطلب الحرف التركي İ المنقط قواعد الحالة التركية للتحويل بشكل صحيح. يضمن استخدام الدالة المراعية للإعدادات المحلية مع الإعدادات المحلية tr التحويل الصحيح.
يمكنك أيضاً التعامل مع الحرف I غير المنقط في التركية، والذي يجب أن يظل غير منقط عند تحويله إلى أحرف صغيرة.
const text = "IRAK";
console.log(text.toLocaleLowerCase("tr"));
// Output: "ırak" (Turkish rules - dotless ı)
console.log(text.toLocaleLowerCase("en"));
// Output: "irak" (English rules - dotted i)
تستخدم كلمة IRAK (العراق بالتركية) الحرف I غير المنقط. تحوله قواعد الحالة التركية إلى الحرف ı الصغير غير المنقط، بينما تحوله القواعد الإنجليزية إلى الحرف i المنقط.
تحديد معرفات الإعدادات المحلية
تقبل كل من toLocaleUpperCase() وtoLocaleLowerCase() معرفات الإعدادات المحلية بتنسيق BCP 47. هذه هي نفس علامات اللغة المستخدمة في جميع أنحاء Intl API وميزات التدويل الأخرى.
const text = "Straße";
console.log(text.toLocaleUpperCase("de-DE"));
// Output: "STRASSE"
console.log(text.toLocaleUpperCase("de-AT"));
// Output: "STRASSE"
console.log(text.toLocaleUpperCase("de-CH"));
// Output: "STRASSE"
تستخدم هذه الأمثلة إعدادات محلية ألمانية مختلفة لألمانيا والنمسا وسويسرا. تكون قواعد تحويل الحالة متسقة بشكل عام عبر المتغيرات الإقليمية لنفس اللغة، لذا تنتج جميعها نفس الناتج.
يمكنك أيضًا تمرير مصفوفة من معرفات اللغات. تستخدم الطريقة اللغة الأولى في المصفوفة.
const text = "istanbul";
const result = text.toLocaleUpperCase(["tr", "en"]);
console.log(result);
// Output: "İSTANBUL"
تطبق الطريقة القواعد التركية لأن tr هي اللغة الأولى في المصفوفة. إذا لم يدعم وقت التشغيل اللغة الأولى، فإنه يعود إلى اللغات اللاحقة في المصفوفة.
استخدام تفضيلات لغة المتصفح
في تطبيقات الويب، يمكنك استخدام تفضيلات لغة متصفح المستخدم لتحديد قواعد تحويل الحالة التي يجب تطبيقها. تُرجع الخاصية navigator.language اللغة المفضلة للمستخدم.
const userLocale = navigator.language;
const text = "istanbul";
const result = text.toLocaleUpperCase(userLocale);
console.log(result);
// Output varies by user's locale
// For Turkish users: "İSTANBUL"
// For English users: "ISTANBUL"
يطبق هذا تلقائيًا القواعد الصحيحة لتحويل الحالة بناءً على إعدادات لغة المستخدم. يرى المستخدمون الأتراك النص محولاً باستخدام القواعد التركية، ويرى المستخدمون الإنجليز النص محولاً باستخدام القواعد الإنجليزية، وهكذا.
يمكنك أيضًا تمرير المصفوفة الكاملة لتفضيلات اللغة لتمكين سلوك الرجوع الاحتياطي.
const text = "istanbul";
const result = text.toLocaleUpperCase(navigator.languages);
console.log(result);
تستخدم الطريقة اللغة الأولى من تفضيلات المستخدم، مما يوفر معالجة أفضل للرجوع الاحتياطي عندما تكون لغات معينة غير متاحة.
مقارنة الطرق القياسية والطرق الواعية باللغة
تعمل الطريقتان القياسيتان toUpperCase() و toLowerCase() بشكل صحيح للغة الإنجليزية ولكن يمكن أن تفشلا مع اللغات الأخرى. تتعامل الطرق الواعية باللغة toLocaleUpperCase() و toLocaleLowerCase() مع جميع اللغات بشكل صحيح من خلال تطبيق القواعد الخاصة باللغة.
const turkish = "Diyarbakır";
// Standard methods (incorrect for Turkish)
console.log(turkish.toUpperCase());
// Output: "DIYARBAKIR" (dotless I - incorrect)
console.log(turkish.toUpperCase().toLowerCase());
// Output: "diyarbakir" (dotted i - lost the dotless ı)
// Locale-aware methods (correct for Turkish)
console.log(turkish.toLocaleUpperCase("tr"));
// Output: "DİYARBAKIR" (dotted İ and dotless I - correct)
console.log(turkish.toLocaleUpperCase("tr").toLocaleLowerCase("tr"));
// Output: "diyarbakır" (preserves both i types - correct)
يحتوي اسم المدينة التركية ديار بكر على كلا النوعين من حرف i. لا يمكن للطرق القياسية الحفاظ على هذا التمييز عند التحويل ذهابًا وإيابًا بين الحالات. تحافظ الطرق الواعية باللغة على الأحرف الصحيحة في كلا الاتجاهين.
بالنسبة للنص الذي يحتوي فقط على أحرف ذات قواعد حالة بسيطة، ينتج كلا النهجين نتائج متطابقة.
const english = "Hello World";
console.log(english.toUpperCase());
// Output: "HELLO WORLD"
console.log(english.toLocaleUpperCase("en"));
// Output: "HELLO WORLD"
يتم تحويل النص الإنجليزي بنفس الطريقة باستخدام أي من الأسلوبين. الإصدار الذي يراعي اللغة المحلية ليس ضروريًا للنص الإنجليزي فقط، ولكن استخدامه يضمن عمل الكود الخاص بك بشكل صحيح إذا كان النص يحتوي على لغات أخرى.
متى يتم استخدام تحويل الحالة الذي يراعي اللغة المحلية
استخدم الأساليب التي تراعي اللغة المحلية عند العمل مع محتوى من إنشاء المستخدم أو نص قد يتضمن لغات متعددة. يضمن ذلك تحويل الحالة بشكل صحيح بغض النظر عن اللغة التي يحتوي عليها النص.
function normalizeUsername(username) {
return username.toLocaleLowerCase();
}
يجب أن تستخدم أسماء المستخدمين وعناوين البريد الإلكتروني ومصطلحات البحث وغيرها من مدخلات المستخدم التحويل الذي يراعي اللغة المحلية. يتعامل هذا مع الأحرف الدولية بشكل صحيح ويمنع المشكلات مع اللغة التركية والحالات الخاصة الأخرى.
استخدم الأساليب القياسية فقط عندما تعلم أن النص يحتوي على أحرف إنجليزية فقط وتحتاج إلى أقصى أداء. يتم تنفيذ الأساليب القياسية بشكل أسرع قليلاً لأنها لا تحتاج إلى التحقق من قواعد اللغة المحلية.
const htmlTag = "<DIV>";
const normalized = htmlTag.toLowerCase();
// Output: "<div>"
تستخدم أسماء علامات HTML وخصائص CSS ومخططات البروتوكول والمعرفات التقنية الأخرى أحرف ASCII ولا تتطلب مراعاة اللغة المحلية. تعمل الأساليب القياسية بشكل صحيح لهذا المحتوى.
كيف يمكن أن يتغير طول الأحرف بعد التحويل
تحويل الحالة ليس دائمًا تعيينًا فرديًا للأحرف. تتوسع بعض الأحرف إلى أحرف متعددة عند تحويلها إلى أحرف كبيرة، مما يؤثر على طول السلسلة النصية.
const german = "groß";
console.log(german.length);
// Output: 4
const uppercase = german.toLocaleUpperCase("de");
console.log(uppercase);
// Output: "GROSS"
console.log(uppercase.length);
// Output: 5
تحتوي الكلمة الألمانية groß على أربعة أحرف. عند تحويلها إلى أحرف كبيرة، يصبح الحرف ß هو SS، مما ينتج عنه GROSS بخمسة أحرف. يزداد طول السلسلة النصية بحرف واحد أثناء التحويل.
يؤثر هذا على العمليات التي تعتمد على طول السلسلة النصية أو مواضع الأحرف. لا تفترض أن الإصدار بأحرف كبيرة أو صغيرة من سلسلة نصية له نفس الطول مثل النص الأصلي.
const text = "Maße";
const positions = [0, 1, 2, 3];
const uppercase = text.toLocaleUpperCase("de");
// "MASSE" (5 characters)
// Original position mapping no longer valid
يتحول الحرف ß في الموضع 2 إلى SS في النسخة بالأحرف الكبيرة، مما يؤدي إلى إزاحة جميع الأحرف اللاحقة. مواضع الأحرف من النص الأصلي لا تتطابق مع المواضع في النص المحول.
إعادة استخدام معاملات اللغة
إذا كنت بحاجة إلى تحويل عدة نصوص باستخدام نفس اللغة، يمكنك تخزين معرف اللغة في متغير وإعادة استخدامه. هذا يجعل الكود الخاص بك أكثر قابلية للصيانة ويضمن معالجة متسقة للغة.
const userLocale = navigator.language;
const city = "istanbul";
const country = "türkiye";
console.log(city.toLocaleUpperCase(userLocale));
console.log(country.toLocaleUpperCase(userLocale));
يحافظ هذا النهج على اختيار اللغة في مكان واحد. إذا كنت بحاجة إلى تغيير اللغة التي تستخدمها، فأنت تحتاج فقط إلى تحديث تعريف المتغير.
بالنسبة للتطبيقات التي تعالج كميات كبيرة من النصوص، لا يوفر هذا فائدة من حيث الأداء. كل استدعاء لـ toLocaleUpperCase() أو toLocaleLowerCase() يقوم بإجراء التحويل بشكل مستقل. على عكس منسقات Intl API، لا يوجد كائن منسق لإعادة استخدامه.