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

تنسيق المدد الزمنية في JavaScript مع الترجمة التلقائية

مقدمة

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

const hours = 1;
const minutes = 46;
const seconds = 40;
const duration = `${hours}h ${minutes}m ${seconds}s`;

ينتج هذا "1h 46m 40s" لجميع المستخدمين بغض النظر عن اللغة. يرى المستخدمون الفرنسيون "1h 46m 40s" بينما يتوقعون "1 h 46 min 40 s". يرى المستخدمون الألمان نفس الاختصارات الإنجليزية. يحصل المستخدمون الإسبان على عدم وجود حرف العطف "y" بين الوحدات.

تحل واجهة برمجة التطبيقات Intl.DurationFormat هذه المشكلة. تقوم بتنسيق المدد الزمنية وفقاً للغة المستخدم والاتفاقيات الثقافية دون مكتبات خارجية أو بناء سلاسل نصية يدوياً.

const duration = { hours: 1, minutes: 46, seconds: 40 };
new Intl.DurationFormat('fr-FR', { style: 'short' }).format(duration);
// "1 h, 46 min et 40 s"

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

ما هي المدد الزمنية

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

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

تتعامل واجهة برمجة التطبيقات Intl.DurationFormat مع المدد. تتعامل واجهة برمجة التطبيقات Intl.DateTimeFormat مع التواريخ والأوقات. استخدم الأداة المناسبة لكل مهمة.

إنشاء منسق مدة زمنية

يأخذ المُنشئ لغة وكائن خيارات. تحدد اللغة لغة الإخراج. تتحكم الخيارات في نمط التنسيق وعرض الوحدة.

const formatter = new Intl.DurationFormat('en', { style: 'long' });

استدعِ format() مع كائن مدة. يحتوي الكائن على خصائص رقمية لوحدات الوقت. قم بتضمين الوحدات التي تريد عرضها فقط.

const duration = { hours: 2, minutes: 30 };
formatter.format(duration);
// "2 hours and 30 minutes"

تدعم واجهة برمجة التطبيقات وحدات الوقت التالية: years، months، weeks، days، hours، minutes، seconds، milliseconds، microseconds، nanoseconds. استخدم أي وحدات تتطابق مع بياناتك.

اختر نمط التنسيق

يتحكم خيار style في كثافة المخرجات. تتوفر أربعة أنماط: long، short، narrow، وdigital.

يستخدم النمط الطويل كلمات كاملة. استخدم هذا للنصوص وإمكانية الوصول.

const duration = { hours: 1, minutes: 46, seconds: 40 };
new Intl.DurationFormat('en', { style: 'long' }).format(duration);
// "1 hour, 46 minutes and 40 seconds"

يستخدم النمط القصير اختصارات شائعة. استخدم هذا عندما تكون المساحة محدودة ولكن سهولة القراءة مهمة.

new Intl.DurationFormat('en', { style: 'short' }).format(duration);
// "1 hr, 46 min and 40 sec"

يستخدم النمط الضيق الحد الأدنى من الأحرف. استخدم هذا للعروض المدمجة مثل واجهات الهاتف المحمول.

new Intl.DurationFormat('en', { style: 'narrow' }).format(duration);
// "1h 46m 40s"

ينتج النمط الرقمي مخرجات تشبه المؤقت بنقطتين رأسيتين. استخدم هذا لمشغلات الوسائط وشاشات العد التنازلي.

new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
// "1:46:40"

الترجمة عبر اللغات

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

const duration = { hours: 1, minutes: 46, seconds: 40 };

new Intl.DurationFormat('en', { style: 'long' }).format(duration);
// "1 hour, 46 minutes and 40 seconds"

new Intl.DurationFormat('fr', { style: 'long' }).format(duration);
// "1 heure, 46 minutes et 40 secondes"

new Intl.DurationFormat('de', { style: 'long' }).format(duration);
// "1 Stunde, 46 Minuten und 40 Sekunden"

new Intl.DurationFormat('es', { style: 'long' }).format(duration);
// "1 hora, 46 minutos y 40 segundos"

new Intl.DurationFormat('ja', { style: 'long' }).format(duration);
// "1時間46分40秒"

لاحظ كيف تستخدم كل لغة كلمات واختصارات وأدوات عطف مختلفة. تستخدم الفرنسية "et"، وتستخدم الألمانية "und"، وتستخدم الإسبانية "y"، ولا تستخدم اليابانية أدوات عطف. تعرف واجهة برمجة التطبيقات هذه القواعد.

تتم ترجمة الأنماط القصيرة والضيقة أيضًا بشكل صحيح.

new Intl.DurationFormat('fr', { style: 'short' }).format(duration);
// "1 h, 46 min et 40 s"

new Intl.DurationFormat('de', { style: 'narrow' }).format(duration);
// "1 Std. 46 Min. 40 Sek."

إنشاء كائنات المدة من حسابات الوقت

كائنات المدة هي كائنات JavaScript عادية بخصائص وحدة الوقت. أنشئها من أي حساب وقت.

حوّل المللي ثانية إلى وحدات المدة بالقسمة على العوامل المناسبة.

const milliseconds = 6400000; // 1 hour, 46 minutes, 40 seconds
const hours = Math.floor(milliseconds / 3600000);
const minutes = Math.floor((milliseconds % 3600000) / 60000);
const seconds = Math.floor((milliseconds % 60000) / 1000);

const duration = { hours, minutes, seconds };
new Intl.DurationFormat('en', { style: 'short' }).format(duration);
// "1 hr, 46 min and 40 sec"

احسب المدة من تاريخين بطرح الطوابع الزمنية.

const start = new Date('2025-01-01T10:00:00');
const end = new Date('2025-01-01T11:46:40');
const diffMs = end - start;

const hours = Math.floor(diffMs / 3600000);
const minutes = Math.floor((diffMs % 3600000) / 60000);
const seconds = Math.floor((diffMs % 60000) / 1000);

const duration = { hours, minutes, seconds };

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

const duration = { minutes: 5, seconds: 30 };
new Intl.DurationFormat('en', { style: 'long' }).format(duration);
// "5 minutes and 30 seconds"

التحكم في الوحدات التي تظهر

بشكل افتراضي، يعرض المنسق جميع الوحدات التي تقدمها في كائن المدة. تحكم في عرض الوحدات باستخدام كائن الخيارات.

حدد نمط العرض لكل وحدة بشكل فردي. الخيارات هي long، short، narrow، numeric، و 2-digit.

const duration = { hours: 1, minutes: 5, seconds: 3 };

new Intl.DurationFormat('en', {
  hours: 'long',
  minutes: 'numeric',
  seconds: '2-digit'
}).format(duration);
// "1 hour, 5:03"

يعرض نمط numeric الرقم بدون تسميات. يضيف نمط 2-digit حشوة الأصفار. استخدم هذه الأنماط للعروض المدمجة التي تجمع بين النص والأرقام.

أخفِ الوحدات بحذفها من كل من كائن المدة والخيارات.

const duration = { hours: 2, minutes: 30 };
new Intl.DurationFormat('en', { style: 'short' }).format(duration);
// "2 hr and 30 min"

يتطلب النمط الرقمي وجود جميع الوحدات من الأكبر إلى الأصغر أو تكوينها بشكل صريح.

const duration = { minutes: 5, seconds: 30 };
new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
// "5:30"

تنسيق مدد مشغل الفيديو

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

function formatVideoDuration(seconds) {
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  const secs = Math.floor(seconds % 60);

  const duration = hours > 0
    ? { hours, minutes, seconds: secs }
    : { minutes, seconds: secs };

  const locale = navigator.language;
  return new Intl.DurationFormat(locale, { style: 'digital' }).format(duration);
}

formatVideoDuration(6400); // "1:46:40"
formatVideoDuration(330);  // "5:30"

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

تنسيق أوقات الرحلات والسفر

تعرض واجهات حجز السفر مدة الرحلة. استخدم النمط القصير لسهولة القراءة في المساحة المحدودة.

function formatFlightDuration(departureDate, arrivalDate, locale) {
  const diffMs = arrivalDate - departureDate;
  const hours = Math.floor(diffMs / 3600000);
  const minutes = Math.floor((diffMs % 3600000) / 60000);

  const duration = { hours, minutes };
  return new Intl.DurationFormat(locale, { style: 'short' }).format(duration);
}

const departure = new Date('2025-06-15T10:30:00');
const arrival = new Date('2025-06-15T18:45:00');

formatFlightDuration(departure, arrival, 'en');
// "8 hr and 15 min"

formatFlightDuration(departure, arrival, 'fr');
// "8 h et 15 min"

تنسيق مدد التمارين والأنشطة

تتتبع تطبيقات اللياقة البدنية مدة التمرين. استخدم النمط الطويل لملخصات الجلسات والنمط الضيق لعروض القوائم.

function formatWorkoutDuration(startTime, endTime, locale) {
  const diffMs = endTime - startTime;
  const hours = Math.floor(diffMs / 3600000);
  const minutes = Math.floor((diffMs % 3600000) / 60000);

  const duration = hours > 0
    ? { hours, minutes }
    : { minutes };

  return new Intl.DurationFormat(locale, { style: 'long' }).format(duration);
}

const workoutStart = new Date('2025-06-15T07:00:00');
const workoutEnd = new Date('2025-06-15T08:15:00');

formatWorkoutDuration(workoutStart, workoutEnd, 'en');
// "1 hour and 15 minutes"

الحصول على أجزاء منسقة للعرض المخصص

تُرجع الدالة formatToParts() مصفوفة من الكائنات تمثل كل جزء من المخرجات المنسقة. استخدم هذا لتنسيق الأجزاء الفردية أو بناء تخطيطات مخصصة.

const duration = { hours: 1, minutes: 46, seconds: 40 };
const parts = new Intl.DurationFormat('en', { style: 'long' }).formatToParts(duration);

يحتوي كل جزء على type و value. تتضمن الأنواع hour، minute، second، literal، وتسميات الوحدات مثل hourUnit، minuteUnit.

[
  { type: "integer", value: "1" },
  { type: "literal", value: " " },
  { type: "unit", value: "hour" },
  { type: "literal", value: ", " },
  { type: "integer", value: "46" },
  { type: "literal", value: " " },
  { type: "unit", value: "minutes" },
  { type: "literal", value: " and " },
  { type: "integer", value: "40" },
  { type: "literal", value: " " },
  { type: "unit", value: "seconds" }
]

قم بالتكرار عبر الأجزاء لتطبيق تنسيق مخصص.

function StyledDuration({ duration }) {
  const parts = new Intl.DurationFormat('en', { style: 'long' }).formatToParts(duration);

  return parts.map((part, i) => {
    if (part.type === 'integer') {
      return <strong key={i}>{part.value}</strong>;
    }
    return <span key={i}>{part.value}</span>;
  });
}

إعادة استخدام نسخ المنسق لتحسين الأداء

إنشاء منسق جديد لكل مدة زمنية يضيف عبئاً إضافياً. قم بإنشاء المنسق مرة واحدة وأعد استخدامه.

const formatter = new Intl.DurationFormat('en', { style: 'short' });

const durations = [
  { hours: 1, minutes: 30 },
  { hours: 2, minutes: 15 },
  { hours: 0, minutes: 45 }
];

durations.map(d => formatter.format(d));
// ["1 hr and 30 min", "2 hr and 15 min", "45 min"]

يحسن هذا النمط الأداء عند تنسيق العديد من المدد الزمنية في الحلقات أو العروض.

الانتقال من بناء السلاسل النصية يدوياً

استبدل دمج السلاسل النصية يدوياً بواجهة برمجة التطبيقات. يقلل هذا من الكود ويضيف الترجمة.

قبل:

function formatDuration(hours, minutes) {
  if (hours > 0 && minutes > 0) {
    return `${hours}h ${minutes}m`;
  } else if (hours > 0) {
    return `${hours}h`;
  } else {
    return `${minutes}m`;
  }
}

بعد:

function formatDuration(hours, minutes, locale) {
  const duration = {};
  if (hours > 0) duration.hours = hours;
  if (minutes > 0) duration.minutes = minutes;

  return new Intl.DurationFormat(locale, { style: 'narrow' }).format(duration);
}

تتعامل نسخة واجهة برمجة التطبيقات مع جميع المنطق الشرطي تلقائياً وتدعم لغات متعددة.

الانتقال من المكتبات

توفر مكتبات مثل Moment.js و date-fns تنسيق المدد الزمنية لكنها تزيد من حجم الحزمة. تلغي واجهة برمجة التطبيقات الأصلية هذا الاعتماد.

استبدل تنسيق المدة الزمنية في Moment.js:

// Before: Moment.js
const duration = moment.duration(6400, 'seconds');
const formatted = duration.hours() + 'h ' + duration.minutes() + 'm';

// After: Intl.DurationFormat
const duration = {
  hours: Math.floor(6400 / 3600),
  minutes: Math.floor((6400 % 3600) / 60)
};
new Intl.DurationFormat('en', { style: 'narrow' }).format(duration);

استبدل تنسيق المدة الزمنية في date-fns:

// Before: date-fns
import { formatDuration, intervalToDuration } from 'date-fns';
const duration = intervalToDuration({ start: 0, end: 6400000 });
const formatted = formatDuration(duration);

// After: Intl.DurationFormat
const ms = 6400000;
const duration = {
  hours: Math.floor(ms / 3600000),
  minutes: Math.floor((ms % 3600000) / 60000),
  seconds: Math.floor((ms % 60000) / 1000)
};
new Intl.DurationFormat('en', { style: 'long' }).format(duration);

توفر واجهة برمجة التطبيقات الأصلية نفس الوظائف بدون اعتماديات.

دعم المتصفحات والبوليفيلات

أصبحت واجهة برمجة التطبيقات Intl.DurationFormat أساسية في مارس 2025. تعمل في أحدث إصدارات Chrome و Edge و Firefox و Safari.

تحقق من الدعم قبل الاستخدام:

if (typeof Intl.DurationFormat !== 'undefined') {
  const formatter = new Intl.DurationFormat('en', { style: 'short' });
  return formatter.format(duration);
} else {
  // Fallback for older browsers
  return `${duration.hours}h ${duration.minutes}m`;
}

للحصول على دعم أوسع، استخدم polyfill. يوفر مشروع FormatJS @formatjs/intl-durationformat.

npm install @formatjs/intl-durationformat

قم بالاستيراد وإضافة polyfill إذا لزم الأمر:

if (!Intl.DurationFormat) {
  await import('@formatjs/intl-durationformat/polyfill');
}

يضيف polyfill حوالي 15 كيلوبايت مضغوطة. قم بتحميله بشكل مشروط لتجنب العبء الإضافي على المتصفحات الحديثة.

متى تستخدم DurationFormat

استخدم Intl.DurationFormat عند عرض الوقت المنقضي أو الوقت المتبقي أو قياسات المدة. يشمل ذلك مشغلات الفيديو والمؤقتات والعد التنازلي وتطبيقات التتبع وحجوزات السفر وعروض مدة الجلسة.

لا تستخدمه للتواريخ أو الأوقات أو الطوابع الزمنية. استخدم Intl.DateTimeFormat لذلك. لا تستخدمه لتعبيرات الوقت النسبي مثل "منذ ساعتين". استخدم Intl.RelativeTimeFormat لذلك.

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