كيفية تنسيق النطاقات مثل 3-5 أو 100-200
استخدم JavaScript لعرض نطاقات الأرقام بتنسيق مناسب للغة المحلية
مقدمة
تظهر نطاقات الأرقام في جميع أنحاء واجهات المستخدم. تُعرض نطاقات الأسعار كـ $100-$200، وأرقام الصفحات كـ 1-10، وتقديرات الكمية كـ 3-5 عناصر. تُوصل هذه النطاقات أن القيمة تقع بين نقطتي نهاية، مما يوفر للمستخدمين معلومات محدودة بدلاً من رقم واحد دقيق.
عندما تقوم بترميز الفاصل بين قيم النطاق بشكل ثابت، فإنك تفترض أن جميع المستخدمين يتبعون نفس الاصطلاحات الطباعية. يستخدم الناطقون بالإنجليزية عادةً الواصلات أو الشرطات المتوسطة للنطاقات، لكن اللغات الأخرى تستخدم رموزاً أو كلمات مختلفة. تستخدم الألمانية "bis" بين الأرقام، بينما تضع بعض اللغات مسافات حول الفواصل.
توفر JavaScript الطريقة formatRange() على Intl.NumberFormat للتعامل مع تنسيق النطاقات تلقائياً. تطبق هذه الطريقة الاصطلاحات الخاصة باللغة المحلية على كل من الأرقام والفاصل، مما يضمن عرض النطاقات بشكل صحيح للمستخدمين حول العالم.
لماذا تحتاج نطاقات الأرقام إلى تنسيق خاص باللغة المحلية
طورت الثقافات المختلفة اصطلاحات مختلفة للتعبير عن النطاقات. تتضمن هذه الاصطلاحات كلاً من رمز الفاصل والمسافات حوله.
في الإنجليزية الأمريكية، تستخدم النطاقات عادةً شرطة متوسطة بدون مسافات: 3-5، 100-200. في بعض أدلة الأسلوب، تظهر مسافات حول الشرطة: 3 - 5. يختلف الاصطلاح الدقيق حسب السياق ومعايير النشر.
في الألمانية، غالباً ما تستخدم النطاقات "bis" كفاصل: 3 bis 5، 100 bis 200. يجعل هذا النهج القائم على الكلمات علاقة النطاق صريحة بدلاً من الاعتماد على علامات الترقيم.
في الإسبانية، يمكن أن تستخدم النطاقات شرطة مثل الإنجليزية أو كلمة "a": 3-5 أو 3 a 5. يعتمد الاختيار على المنطقة الناطقة بالإسبانية المحددة والسياق.
عند تنسيق النطاقات التي تتضمن عملات أو وحدات، تزداد التعقيدات. قد يظهر نطاق الأسعار كـ $100-$200 في الإنجليزية الأمريكية، ولكن كـ 100 €-200 € في الألمانية، أو 100-200 € مع ظهور الرمز مرة واحدة فقط. تضع اللغات المحلية المختلفة رموز العملات بشكل مختلف وتتعامل مع التكرار بشكل مختلف.
يتطلب تنسيق النطاقات يدوياً معرفة هذه الاتفاقيات وتنفيذ منطق خاص باللغة المحلية. تتضمن واجهة برمجة التطبيقات Intl هذه المعرفة، وتطبق التنسيق المناسب بناءً على اللغة المحلية.
استخدام formatRange لتنسيق نطاقات الأرقام
تقبل الدالة formatRange() رقمين وتُرجع سلسلة نصية منسقة تمثل النطاق. أنشئ نسخة من Intl.NumberFormat مع اللغة المحلية والخيارات المطلوبة، ثم استدعِ formatRange() مع قيم البداية والنهاية.
const formatter = new Intl.NumberFormat("en-US");
console.log(formatter.formatRange(3, 5));
// Output: "3–5"
console.log(formatter.formatRange(100, 200));
// Output: "100–200"
console.log(formatter.formatRange(1000, 5000));
// Output: "1,000–5,000"
يطبق المنسق فواصل الآلاف على كلا الرقمين في النطاق ويستخدم فاصلاً مناسباً بينهما. بالنسبة للإنجليزية الأمريكية، هذا هو شرطة en بدون مسافات.
يمكنك تنسيق نفس النطاق للغات محلية مختلفة عن طريق تغيير معرف اللغة المحلية.
const usFormatter = new Intl.NumberFormat("en-US");
console.log(usFormatter.formatRange(100, 200));
// Output: "100–200"
const deFormatter = new Intl.NumberFormat("de-DE");
console.log(deFormatter.formatRange(100, 200));
// Output: "100–200"
const esFormatter = new Intl.NumberFormat("es-ES");
console.log(esFormatter.formatRange(100, 200));
// Output: "100-200"
تطبق كل لغة محلية اتفاقياتها الخاصة للفاصل والمسافات. تتعامل واجهة برمجة التطبيقات مع هذه التفاصيل تلقائياً بناءً على المعايير الطباعية للغة المحلية.
تنسيق نطاقات العملات
يعمل تنسيق النطاقات مع أي خيارات تنسيق أرقام، بما في ذلك العملات. عند تنسيق نطاقات العملات، يتعامل المنسق مع كل من موضع رمز العملة وفاصل النطاق.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 0
});
console.log(formatter.formatRange(100, 200));
// Output: "$100 – $200"
console.log(formatter.formatRange(1000, 5000));
// Output: "$1,000 – $5,000"
يضع المنسق رمز العملة قبل كل رقم في النطاق. هذا يوضح أن كلا القيمتين تمثلان مبالغ عملة.
تضع اللغات المحلية المختلفة رموز العملات بشكل مختلف.
const usFormatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 0
});
console.log(usFormatter.formatRange(100, 200));
// Output: "$100 – $200"
const deFormatter = new Intl.NumberFormat("de-DE", {
style: "currency",
currency: "EUR",
maximumFractionDigits: 0
});
console.log(deFormatter.formatRange(100, 200));
// Output: "100–200 €"
يضع المنسق الألماني رمز اليورو بعد النطاق بدلاً من وضعه قبل كل رقم. يتبع هذا الاتفاقيات الطباعية الألمانية لنطاقات العملات.
ماذا يحدث عندما تكون قيم النطاق متساوية تقريباً
عندما تُقرَّب قيمتا البداية والنهاية إلى نفس الرقم بعد التنسيق، يطوي المنسق النطاق وقد يضيف رمز تقريب.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 0
});
console.log(formatter.formatRange(100, 200));
// Output: "$100 – $200"
console.log(formatter.formatRange(100, 120));
// Output: "$100 – $120"
console.log(formatter.formatRange(100.2, 100.8));
// Output: "~$100"
يُظهر المثال الثالث قيمتين تُقرَّبان إلى نفس الرقم الصحيح. بدلاً من عرض "$100 – $100"، والذي لا ينقل أي معلومات عن النطاق، يُخرج المنسق "~$100". يشير رمز التلدة إلى أن القيمة تقريبية.
ينطبق هذا السلوك عندما تتسبب خيارات التنسيق في ظهور قيمتي البداية والنهاية متطابقتين.
const formatter = new Intl.NumberFormat("en-US", {
maximumFractionDigits: 1
});
console.log(formatter.formatRange(2.9, 3.1));
// Output: "~3"
console.log(formatter.formatRange(2.94, 2.96));
// Output: "~2.9"
يُدرج المنسق رمز التقريب فقط عند الحاجة. عندما تُقرَّب القيم إلى أرقام مختلفة، يعرضها كنطاق قياسي.
تنسيق النطاقات بمنازل عشرية
يحافظ تنسيق النطاق على إعدادات المنازل العشرية من خيارات المنسق. يمكنك التحكم في الدقة لكلتا القيمتين في النطاق.
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(formatter.formatRange(3.5, 5.7));
// Output: "3.50–5.70"
console.log(formatter.formatRange(100, 200));
// Output: "100.00–200.00"
يطبق المنسق إعدادات المنازل العشرية على كلا الرقمين في النطاق. يضمن هذا دقة متسقة عبر عرض النطاق بالكامل.
يمكنك دمج التنسيق العشري مع العملة أو الأنماط الأخرى.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(formatter.formatRange(99.99, 199.99));
// Output: "$99.99 – $199.99"
تنسيق نطاقات الأرقام بلغات مختلفة
يتكيف تنسيق النطاق مع اتفاقيات كل لغة للأرقام والفواصل والمسافات.
const enFormatter = new Intl.NumberFormat("en-US");
console.log(enFormatter.formatRange(1000, 5000));
// Output: "1,000–5,000"
const deFormatter = new Intl.NumberFormat("de-DE");
console.log(deFormatter.formatRange(1000, 5000));
// Output: "1.000–5.000"
const frFormatter = new Intl.NumberFormat("fr-FR");
console.log(frFormatter.formatRange(1000, 5000));
// Output: "1 000–5 000"
const jaFormatter = new Intl.NumberFormat("ja-JP");
console.log(jaFormatter.formatRange(1000, 5000));
// Output: "1,000~5,000"
تستخدم الإنجليزية الفواصل لفواصل الآلاف وشرطة متوسطة للنطاق. تستخدم الألمانية النقاط للآلاف وشرطة متوسطة. تستخدم الفرنسية المسافات للآلاف وشرطة متوسطة. تستخدم اليابانية الفواصل للآلاف وشرطة موجية (~) للنطاق.
تمتد هذه الاختلافات إلى تنسيق العملات.
const enFormatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
console.log(enFormatter.formatRange(100, 200));
// Output: "$100.00 – $200.00"
const deFormatter = new Intl.NumberFormat("de-DE", {
style: "currency",
currency: "EUR"
});
console.log(deFormatter.formatRange(100, 200));
// Output: "100,00–200,00 €"
const jaFormatter = new Intl.NumberFormat("ja-JP", {
style: "currency",
currency: "JPY"
});
console.log(jaFormatter.formatRange(100, 200));
// Output: "¥100~¥200"
تطبق كل لغة قواعدها الخاصة لموضع رمز العملة والفواصل العشرية وفواصل النطاق. تتعامل واجهة برمجة التطبيقات مع جميع هذه الاختلافات تلقائياً.
دمج formatRange مع الترميز المضغوط
يعمل تنسيق النطاق مع الترميز المضغوط، مما يتيح لك عرض نطاقات مثل 1K-5K أو 1M-5M.
const formatter = new Intl.NumberFormat("en-US", {
notation: "compact"
});
console.log(formatter.formatRange(1000, 5000));
// Output: "1K–5K"
console.log(formatter.formatRange(1000000, 5000000));
// Output: "1M–5M"
console.log(formatter.formatRange(1200, 4800));
// Output: "1.2K–4.8K"
يطبق المنسق الترميز المضغوط على كلا القيمتين في النطاق. يحافظ هذا على الناتج موجزاً مع الاستمرار في نقل معلومات النطاق.
عندما يمتد النطاق عبر مستويات مختلفة من الحجم، يتعامل المنسق مع كل قيمة بشكل مناسب.
const formatter = new Intl.NumberFormat("en-US", {
notation: "compact"
});
console.log(formatter.formatRange(500, 1500));
// Output: "500–1.5K"
console.log(formatter.formatRange(900000, 1200000));
// Output: "900K–1.2M"
قد لا تستخدم قيمة البداية الترميز المضغوط بينما تستخدمه قيمة النهاية، أو قد تستخدمان مؤشرات حجم مختلفة. يتخذ المنسق هذه القرارات بناءً على حجم كل قيمة.
استخدام formatRangeToParts للتنسيق المخصص
تُرجع طريقة formatRangeToParts() مصفوفة من الكائنات تمثل أجزاء النطاق المنسق. يتيح لك هذا تنسيق أو معالجة المكونات الفردية للنطاق.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 0
});
const parts = formatter.formatRangeToParts(100, 200);
console.log(parts);
الناتج عبارة عن مصفوفة من الكائنات، كل منها يحتوي على خصائص type وvalue وsource.
[
{ type: "currency", value: "$", source: "startRange" },
{ type: "integer", value: "100", source: "startRange" },
{ type: "literal", value: " – ", source: "shared" },
{ type: "currency", value: "$", source: "endRange" },
{ type: "integer", value: "200", source: "endRange" }
]
تحدد خاصية type ما يمثله الجزء: رمز العملة أو العدد الصحيح أو الفاصل العشري أو النص الحرفي. تحتوي خاصية value على النص المنسق. تشير خاصية source إلى ما إذا كان الجزء ينتمي إلى قيمة البداية أو قيمة النهاية أو مشترك بينهما.
يمكنك استخدام هذه الأجزاء لإنشاء HTML مخصص بتنسيقات مختلفة للمكونات المختلفة.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 0
});
const parts = formatter.formatRangeToParts(100, 200);
let html = "";
parts.forEach(part => {
if (part.type === "currency") {
html += `<span class="currency-symbol">${part.value}</span>`;
} else if (part.type === "integer") {
html += `<span class="amount">${part.value}</span>`;
} else if (part.type === "literal") {
html += `<span class="separator">${part.value}</span>`;
} else {
html += part.value;
}
});
console.log(html);
// Output: <span class="currency-symbol">$</span><span class="amount">100</span><span class="separator"> – </span><span class="currency-symbol">$</span><span class="amount">200</span>
تتيح لك هذه التقنية تطبيق فئات CSS أو إضافة تلميحات أدوات أو تنفيذ سلوكيات مخصصة أخرى مع الحفاظ على التنسيق الصحيح الخاص باللغة.
التعامل مع الحالات الاستثنائية باستخدام formatRange
تتضمن طريقة formatRange() معالجة الأخطاء للمدخلات غير الصالحة. إذا كانت أي من المعاملات undefined، يتم طرح TypeError. إذا كانت أي من المعاملات NaN أو لا يمكن تحويلها إلى رقم، يتم طرح RangeError.
const formatter = new Intl.NumberFormat("en-US");
try {
console.log(formatter.formatRange(100, undefined));
} catch (error) {
console.log(error.name);
// Output: "TypeError"
}
try {
console.log(formatter.formatRange(NaN, 200));
} catch (error) {
console.log(error.name);
// Output: "RangeError"
}
عند العمل مع مدخلات المستخدم أو البيانات من مصادر خارجية، تحقق من أن القيم أرقام صالحة قبل تمريرها إلى formatRange().
تقبل الطريقة الأرقام أو قيم BigInt أو السلاسل النصية التي تمثل أرقاماً صالحة.
const formatter = new Intl.NumberFormat("en-US");
console.log(formatter.formatRange(100, 200));
// Output: "100–200"
console.log(formatter.formatRange(100n, 200n));
// Output: "100–200"
console.log(formatter.formatRange("100", "200"));
// Output: "100–200"
يتم تحليل المدخلات النصية كأرقام، مع الحفاظ على الدقة دون مشاكل تحويل الفاصلة العائمة.
متى تستخدم formatRange مقابل التنسيق اليدوي
استخدم formatRange() عند عرض النطاقات للمستخدمين. ينطبق هذا على نطاقات الأسعار ونطاقات الكميات ونطاقات القياسات وأرقام الصفحات أو أي قيم محدودة أخرى. تضمن الطريقة التنسيق الصحيح الخاص باللغة المحلية دون الحاجة إلى تنفيذ منطق الفواصل.
تجنب formatRange() عندما تحتاج إلى عرض قيم منفصلة متعددة غير مرتبطة دلالياً كنطاق. على سبيل المثال، عرض قائمة أسعار مثل "$100, $150, $200" يجب أن يستخدم استدعاءات format() العادية لكل قيمة بدلاً من معاملتها كنطاقات.
تجنب أيضاً formatRange() عندما لا تكون العلاقة بين القيم نطاقاً رقمياً. إذا كنت تعرض مقارنة أو فرقاً، استخدم التنسيق المناسب لذلك السياق بدلاً من تنسيق النطاق.