كيفية تقسيم المخرجات المنسقة إلى أجزاء للتنسيق
استخدم formatToParts() للوصول إلى المكونات الفردية للمخرجات المنسقة لتطبيق تنسيق مخصص
مقدمة
تُرجع الدالة format() في المُنسِّقات في JavaScript نصوصاً كاملة مثل "$1,234.56" أو "January 15, 2025". يعمل هذا بشكل جيد للعرض البسيط، لكن لا يمكنك تنسيق الأجزاء الفردية بشكل مختلف. لا يمكنك جعل رمز العملة غامقاً، أو تلوين اسم الشهر بشكل مختلف، أو تطبيق علامات مخصصة على مكونات محددة.
توفر JavaScript الدالة formatToParts() لحل هذه المشكلة. بدلاً من إرجاع نص واحد، تُرجع مصفوفة من الكائنات، يمثل كل منها جزءاً واحداً من المخرجات المنسقة. كل جزء له نوع مثل currency، أو month، أو element، وقيمة تحتوي على النص الفعلي. يمكنك بعد ذلك معالجة هذه الأجزاء لتطبيق تنسيق مخصص، أو بناء تخطيطات معقدة، أو دمج المحتوى المنسق في واجهات مستخدم غنية.
الدالة formatToParts() متاحة في عدة مُنسِّقات Intl، بما في ذلك NumberFormat، وDateTimeFormat، وListFormat، وRelativeTimeFormat، وDurationFormat. هذا يجعلها نمطاً متسقاً عبر جميع عمليات التنسيق الدولية في JavaScript.
لماذا لا يمكن تنسيق النصوص المنسقة بسهولة
عندما تتلقى نصاً منسقاً مثل "$1,234.56"، لا يمكنك تحديد مكان انتهاء رمز العملة وبداية الرقم بسهولة. تضع اللغات المختلفة الرموز في مواضع مختلفة. تستخدم بعض اللغات فواصل مختلفة. يتطلب تحليل هذه النصوص بشكل موثوق منطقاً معقداً يكرر قواعد التنسيق المطبقة بالفعل في واجهة برمجة التطبيقات Intl.
لنأخذ مثالاً على لوحة معلومات تعرض مبالغ مالية مع رمز العملة بلون مختلف. مع format()، ستحتاج إلى:
- اكتشاف الأحرف التي تمثل رمز العملة
- مراعاة المسافات بين الرمز والرقم
- التعامل مع مواضع الرموز المختلفة عبر اللغات
- تحليل النص بعناية لتجنب كسر الرقم
هذا النهج هش وعرضة للأخطاء. أي تغيير في قواعد تنسيق اللغة يكسر منطق التحليل الخاص بك.
نفس المشكلة موجودة في التواريخ والقوائم والمخرجات المنسقة الأخرى. لا يمكنك تحليل النصوص المنسقة بشكل موثوق لتحديد المكونات دون إعادة تطبيق قواعد التنسيق الخاصة باللغة.
الدالة formatToParts() تلغي هذه المشكلة من خلال توفير المكونات بشكل منفصل. تتلقى بيانات منظمة تخبرك بالضبط أي جزء هو أي، بغض النظر عن اللغة.
كيفية عمل formatToParts
تعمل الدالة formatToParts() بشكل مطابق للدالة format() باستثناء قيمة الإرجاع. تقوم بإنشاء منسق بنفس الخيارات، ثم تستدعي formatToParts() بدلاً من format().
تُرجع الدالة مصفوفة من الكائنات. يحتوي كل كائن على خاصيتين:
type: يحدد ما يمثله الجزء، مثلcurrency، أوmonth، أوliteralvalue: يحتوي على النص الفعلي لذلك الجزء
تظهر الأجزاء بنفس الترتيب الذي ستظهر به في المخرجات المنسقة. يمكنك التحقق من ذلك عن طريق دمج جميع القيم معاً، مما ينتج نفس المخرجات تماماً كما لو استدعيت format().
هذا النمط متسق عبر جميع المنسقات التي تدعم formatToParts(). تختلف أنواع الأجزاء المحددة حسب المنسق، لكن البنية دائماً نفسها.
تقسيم الأرقام المنسقة إلى أجزاء
يوفر منسق NumberFormat الدالة formatToParts() لتقسيم الأرقام المنسقة. يعمل هذا مع الأرقام الأساسية والعملات والنسب المئوية وأنماط الأرقام الأخرى.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
const parts = formatter.formatToParts(1234.56);
console.log(parts);
ينتج هذا مصفوفة من الكائنات:
[
{ type: "currency", value: "$" },
{ type: "integer", value: "1" },
{ type: "group", value: "," },
{ type: "integer", value: "234" },
{ type: "decimal", value: "." },
{ type: "fraction", value: "56" }
]
يحدد كل كائن ما يمثله الجزء ويوفر قيمته. يمثل النوع currency رمز العملة. يمثل النوع integer أرقام الأعداد الصحيحة. يمثل النوع group فاصل الآلاف. يمثل النوع decimal الفاصلة العشرية. يمثل النوع fraction الأرقام بعد الفاصلة العشرية.
يمكنك التحقق من أن الأجزاء تطابق المخرجات المنسقة:
const formatted = parts.map(part => part.value).join("");
console.log(formatted);
// Output: "$1,234.56"
تنتج الأجزاء المتسلسلة نفس المخرجات تمامًا كما لو تم استدعاء format().
تنسيق رموز العملات في الأرقام المنسقة
حالة الاستخدام الأساسية لـ formatToParts() هي تطبيق أنماط مختلفة على مكونات مختلفة. يمكنك معالجة مصفوفة الأجزاء لتغليف أنواع معينة في عناصر HTML.
جعل رمز العملة غامقًا:
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
const parts = formatter.formatToParts(1234.56);
const html = parts
.map(part => {
if (part.type === "currency") {
return `<strong>${part.value}</strong>`;
}
return part.value;
})
.join("");
console.log(html);
// Output: "<strong>$</strong>1,234.56"
يعمل هذا النهج مع أي لغة ترميز. يمكنك إنشاء HTML أو JSX أو أي تنسيق آخر من خلال معالجة مصفوفة الأجزاء.
تنسيق الأجزاء العشرية بشكل مختلف:
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2
});
const parts = formatter.formatToParts(1234.5);
const html = parts
.map(part => {
if (part.type === "decimal" || part.type === "fraction") {
return `<span class="text-gray-500">${part.value}</span>`;
}
return part.value;
})
.join("");
console.log(html);
// Output: "1,234<span class="text-gray-500">.50</span>"
هذا النمط شائع في عروض الأسعار حيث يظهر الجزء العشري بحجم أصغر أو بلون أفتح.
تقسيم التواريخ المنسقة إلى أجزاء
يوفر منسق DateTimeFormat الدالة formatToParts() لتقسيم التواريخ والأوقات المنسقة.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
console.log(parts);
ينتج هذا مصفوفة من الكائنات:
[
{ type: "month", value: "January" },
{ type: "literal", value: " " },
{ type: "day", value: "15" },
{ type: "literal", value: ", " },
{ type: "year", value: "2025" }
]
يمثل النوع month اسم الشهر أو رقمه. يمثل النوع day يوم الشهر. يمثل النوع year السنة. يمثل النوع literal المسافات أو علامات الترقيم أو النصوص الأخرى التي يدرجها المنسق.
تنسيق أسماء الأشهر في التواريخ المنسقة
يمكنك تطبيق تنسيق مخصص على مكونات التاريخ باستخدام نفس النمط المستخدم مع الأرقام.
جعل اسم الشهر غامقاً:
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
const html = parts
.map(part => {
if (part.type === "month") {
return `<strong>${part.value}</strong>`;
}
return part.value;
})
.join("");
console.log(html);
// Output: "<strong>January</strong> 15, 2025"
تنسيق مكونات تاريخ متعددة:
const formatter = new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
const html = parts
.map(part => {
switch (part.type) {
case "weekday":
return `<span class="font-bold">${part.value}</span>`;
case "month":
return `<span class="text-blue-600">${part.value}</span>`;
case "year":
return `<span class="text-gray-500">${part.value}</span>`;
default:
return part.value;
}
})
.join("");
console.log(html);
// Output: "<span class="font-bold">Wednesday</span>, <span class="text-blue-600">January</span> 15, <span class="text-gray-500">2025</span>"
يتيح هذا التحكم الدقيق تنسيقاً محدداً لكل مكون.
تقسيم القوائم المنسقة إلى أجزاء
يوفر منسق ListFormat الدالة formatToParts() لتقسيم القوائم المنسقة.
const formatter = new Intl.ListFormat("en-US", {
style: "long",
type: "conjunction"
});
const items = ["apples", "oranges", "bananas"];
const parts = formatter.formatToParts(items);
console.log(parts);
ينتج هذا مصفوفة من الكائنات:
[
{ type: "element", value: "apples" },
{ type: "literal", value: ", " },
{ type: "element", value: "oranges" },
{ type: "literal", value: ", and " },
{ type: "element", value: "bananas" }
]
يمثل النوع element كل عنصر في القائمة. يمثل النوع literal الفواصل وأدوات العطف التي يضيفها المنسق.
تنسيق عناصر القائمة بشكل فردي
يمكنك تطبيق تنسيق مخصص على عناصر القائمة باستخدام نفس النمط.
جعل عناصر القائمة غامقة:
const formatter = new Intl.ListFormat("en-US", {
style: "long",
type: "conjunction"
});
const items = ["apples", "oranges", "bananas"];
const parts = formatter.formatToParts(items);
const html = parts
.map(part => {
if (part.type === "element") {
return `<strong>${part.value}</strong>`;
}
return part.value;
})
.join("");
console.log(html);
// Output: "<strong>apples</strong>, <strong>oranges</strong>, and <strong>bananas</strong>"
تنسيق عناصر قائمة محددة:
const formatter = new Intl.ListFormat("en-US", {
style: "long",
type: "conjunction"
});
const items = ["apples", "oranges", "bananas"];
const parts = formatter.formatToParts(items);
let itemIndex = 0;
const html = parts
.map(part => {
if (part.type === "element") {
const currentIndex = itemIndex++;
if (currentIndex === 0) {
return `<span class="text-green-600">${part.value}</span>`;
}
return part.value;
}
return part.value;
})
.join("");
console.log(html);
// Output: "<span class="text-green-600">apples</span>, oranges, and bananas"
يتيح لك هذا النهج إبراز عناصر محددة مع الحفاظ على التنسيق الصحيح الخاص بكل لغة.
تقسيم الأوقات النسبية المنسقة إلى أجزاء
يوفر منسق RelativeTimeFormat الدالة formatToParts() لتقسيم تعبيرات الوقت النسبي.
const formatter = new Intl.RelativeTimeFormat("en-US", {
numeric: "auto"
});
const parts = formatter.formatToParts(-1, "day");
console.log(parts);
ينتج هذا مصفوفة من الكائنات:
{/* CODE_PLACEHOLDER_abd978769d38434511f86f02f249689b */)}
للأوقات النسبية الرقمية:
const formatter = new Intl.RelativeTimeFormat("en-US", {
numeric: "always"
});
const parts = formatter.formatToParts(-3, "day");
console.log(parts);
// [
// { type: "integer", value: "3" },
// { type: "literal", value: " days ago" }
// ]
يمثل النوع integer القيمة الرقمية. يمثل النوع literal وحدة الوقت النسبي والاتجاه.
تقسيم المدد الزمنية المنسقة إلى أجزاء
يوفر منسق DurationFormat الدالة formatToParts() لتقسيم المدد الزمنية المنسقة.
const formatter = new Intl.DurationFormat("en-US", {
style: "long"
});
const parts = formatter.formatToParts({
hours: 2,
minutes: 30,
seconds: 15
});
console.log(parts);
ينتج هذا مصفوفة من الكائنات مشابهة لـ:
[
{ type: "integer", value: "2" },
{ type: "literal", value: " hours, " },
{ type: "integer", value: "30" },
{ type: "literal", value: " minutes, " },
{ type: "integer", value: "15" },
{ type: "literal", value: " seconds" }
]
يمثل النوع integer القيم الرقمية. يمثل النوع literal أسماء الوحدات والفواصل.
بناء HTML من الأجزاء المنسقة
يمكنك إنشاء دالة قابلة لإعادة الاستخدام تعالج الأجزاء وتطبق قواعد التنسيق بشكل متسق.
function formatWithStyles(parts, styleMap) {
return parts
.map(part => {
const style = styleMap[part.type];
if (style) {
return `<span class="${style}">${part.value}</span>`;
}
return part.value;
})
.join("");
}
const numberFormatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
const parts = numberFormatter.formatToParts(1234.56);
const html = formatWithStyles(parts, {
currency: "font-bold text-gray-700",
integer: "text-2xl",
fraction: "text-sm text-gray-500"
});
console.log(html);
// Output: "<span class="font-bold text-gray-700">$</span><span class="text-2xl">1</span>,<span class="text-2xl">234</span>.<span class="text-sm text-gray-500">56</span>"
يفصل هذا النمط قواعد التنسيق عن منطق التنسيق، مما يسهل الصيانة وإعادة الاستخدام.
فهم ترتيب الأجزاء الخاص باللغة المحلية
تحافظ مصفوفة الأجزاء على قواعد التنسيق الخاصة باللغة المحلية تلقائيًا. تضع اللغات المحلية المختلفة المكونات بترتيبات مختلفة وتستخدم تنسيقات مختلفة، لكن formatToParts() تتعامل مع هذه الاختلافات.
const usdFormatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
console.log(usdFormatter.formatToParts(1234.56));
// [
// { type: "currency", value: "$" },
// { type: "integer", value: "1" },
// { type: "group", value: "," },
// { type: "integer", value: "234" },
// { type: "decimal", value: "." },
// { type: "fraction", value: "56" }
// ]
const eurFormatter = new Intl.NumberFormat("de-DE", {
style: "currency",
currency: "EUR"
});
console.log(eurFormatter.formatToParts(1234.56));
// [
// { type: "integer", value: "1" },
// { type: "group", value: "." },
// { type: "integer", value: "234" },
// { type: "decimal", value: "," },
// { type: "fraction", value: "56" },
// { type: "literal", value: " " },
// { type: "currency", value: "€" }
// ]
يضع التنسيق الألماني العملة بعد الرقم مع مسافة. فاصل المجموعات هو نقطة، والفاصل العشري هو فاصلة. يعالج كود التنسيق الخاص بك مصفوفة الأجزاء بنفس الطريقة بغض النظر عن اللغة المحلية، ويتكيف التنسيق تلقائيًا.
إنشاء عروض منسقة يمكن الوصول إليها
يمكنك استخدام formatToParts() لإضافة سمات إمكانية الوصول إلى المخرجات المنسقة. يساعد هذا قارئات الشاشة على الإعلان عن القيم بشكل صحيح.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
function formatAccessible(number) {
const parts = formatter.formatToParts(number);
const formatted = parts.map(part => part.value).join("");
return `<span aria-label="${number} US dollars">${formatted}</span>`;
}
console.log(formatAccessible(1234.56));
// Output: "<span aria-label="1234.56 US dollars">$1,234.56</span>"
يضمن هذا أن قارئات الشاشة تعلن عن كل من قيمة العرض المنسقة والقيمة الرقمية الأساسية مع السياق المناسب.
دمج formatToParts مع مكونات إطار العمل
يمكن لأطر العمل الحديثة مثل React استخدام formatToParts() لبناء المكونات بكفاءة.
function CurrencyDisplay({ value, locale, currency }) {
const formatter = new Intl.NumberFormat(locale, {
style: "currency",
currency: currency
});
const parts = formatter.formatToParts(value);
return (
<span className="currency-display">
{parts.map((part, index) => {
if (part.type === "currency") {
return <strong key={index}>{part.value}</strong>;
}
if (part.type === "fraction" || part.type === "decimal") {
return <span key={index} className="text-sm text-gray-500">{part.value}</span>;
}
return <span key={index}>{part.value}</span>;
})}
</span>
);
}
يطبق هذا المكون تنسيقات مختلفة على أجزاء مختلفة مع الحفاظ على التنسيق الصحيح لأي لغة وعملة.
متى تستخدم formatToParts
استخدم format() عندما تحتاج إلى نص منسق بسيط دون أي تخصيص. هذه هي الحالة الشائعة لمعظم سيناريوهات العرض.
استخدم formatToParts() عندما تحتاج إلى:
- تطبيق تنسيقات مختلفة على أجزاء مختلفة من المخرجات المنسقة
- بناء HTML أو JSX مع محتوى منسق
- إضافة سمات أو بيانات وصفية إلى مكونات محددة
- دمج المخرجات المنسقة في تخطيطات معقدة
- معالجة المخرجات المنسقة برمجياً
- إنشاء تصميمات مرئية مخصصة تتطلب تحكماً دقيقاً
تتطلب طريقة formatToParts() عبئاً إضافياً طفيفاً مقارنة بـ format() لأنها تنشئ مصفوفة من الكائنات بدلاً من نص واحد. هذا الفرق ضئيل للتطبيقات النموذجية، ولكن إذا كنت تنسق آلاف القيم في الثانية، فإن format() يقدم أداءً أفضل.
بالنسبة لمعظم التطبيقات، اختر بناءً على احتياجات التنسيق الخاصة بك بدلاً من مخاوف الأداء. إذا كنت لا تحتاج إلى تخصيص المخرجات، استخدم format(). إذا كنت بحاجة إلى تنسيق أو ترميز مخصص، استخدم formatToParts().
أنواع الأجزاء الشائعة عبر المنسقات
تنتج المنسقات المختلفة أنواعاً مختلفة من الأجزاء، لكن بعض الأنواع تظهر عبر منسقات متعددة:
literal: المسافات أو علامات الترقيم أو نصوص أخرى تضاف بواسطة التنسيق. تظهر في التواريخ والأرقام والقوائم والمدد الزمنية.integer: أرقام الأعداد الصحيحة. تظهر في الأرقام والأوقات النسبية والمدد الزمنية.decimal: الفاصل العشري. يظهر في الأرقام.fraction: الأرقام العشرية. تظهر في الأرقام.
تشمل الأنواع الخاصة بالمنسقات:
- الأرقام:
currency،group،percentSign،minusSign،plusSign،unit،compact،exponentInteger - التواريخ:
weekday،era،year،month،day،hour،minute،second،dayPeriod،timeZoneName - القوائم:
element - الأوقات النسبية: تظهر القيم الرقمية كـ
integer، ويظهر النص كـliteral
يساعدك فهم هذه الأنواع على كتابة كود التنسيق الذي يتعامل مع أي مخرجات منسق بشكل صحيح.