Comment afficher des libellés localisés pour les champs de date et d'heure ?
Utilisez Intl.DisplayNames pour obtenir les libellés des champs et Intl.DateTimeFormat pour obtenir les noms des mois et des jours de la semaine dans n'importe quelle langue.
Introduction
Lorsque vous créez des formulaires de saisie de date et d'heure, vous avez besoin d'étiquettes qui décrivent chaque champ. Un sélecteur de date nécessite des étiquettes comme "Mois", "Année" et "Jour". Un sélecteur d'heure nécessite des étiquettes comme "Heure" et "Minute". Ces étiquettes doivent apparaître dans la langue de l'utilisateur.
Coder en dur ces étiquettes en anglais ne fonctionne pas pour les applications internationales. Un utilisateur français s'attend à voir "Mois" et "Année", tandis qu'un utilisateur espagnol cherche "Mes" et "Año". Vous avez besoin d'un système qui fournit automatiquement ces étiquettes dans n'importe quelle langue.
JavaScript propose deux API complémentaires pour cela. L'API Intl.DisplayNames vous donne des étiquettes de champ comme "Mois" et "Année". L'API Intl.DateTimeFormat vous donne les valeurs réelles pour ces champs, comme les noms des mois et des jours de la semaine.
Comprendre les étiquettes des champs de date et d'heure
Les interfaces de date et d'heure nécessitent deux types d'étiquettes. Les étiquettes de champ décrivent quel type de données va dans chaque entrée. Les valeurs de champ sont les données réelles qui apparaissent dans les listes déroulantes et les sélecteurs.
Les étiquettes de champ comprennent des mots comme "Année", "Mois", "Jour", "Heure", "Minute" et "Seconde". Elles étiquettent les champs du formulaire eux-mêmes.
Les valeurs de champ comprennent les noms des mois comme "Janvier" et "Février", les noms des jours de la semaine comme "Lundi" et "Mardi", et les étiquettes de période comme "AM" et "PM". Elles alimentent les listes déroulantes et les listes de sélection.
Un formulaire de date complet a besoin des deux types d'étiquettes.
<label>Mois</label>
<select>
<option>Janvier</option>
<option>Février</option>
<option>Mars</option>
<!-- plus de mois -->
</select>
<label>Année</label>
<input type="number" />
"Mois" et "Janvier" nécessitent tous deux une localisation, mais ils requièrent des approches différentes.
Obtenir des étiquettes de champ avec Intl.DisplayNames
Le constructeur Intl.DisplayNames avec type: "dateTimeField" renvoie des étiquettes localisées pour les composants de date et d'heure.
const labels = new Intl.DisplayNames('en-US', { type: 'dateTimeField' });
console.log(labels.of('year'));
// "year"
console.log(labels.of('month'));
// "month"
console.log(labels.of('day'));
// "day"
console.log(labels.of('hour'));
// "hour"
console.log(labels.of('minute'));
// "minute"
console.log(labels.of('second'));
// "second"
La méthode of() prend un code de champ et renvoie son étiquette localisée. L'étiquette correspond aux conventions de la locale spécifiée.
Vous pouvez obtenir des étiquettes dans n'importe quelle langue en changeant la locale.
// Étiquettes en espagnol
const esLabels = new Intl.DisplayNames('es-ES', { type: 'dateTimeField' });
console.log(esLabels.of('year'));
// "año"
console.log(esLabels.of('month'));
// "mes"
console.log(esLabels.of('day'));
// "día"
console.log(esLabels.of('hour'));
// "hora"
console.log(esLabels.of('minute'));
// "minuto"
// Étiquettes en français
const frLabels = new Intl.DisplayNames('fr-FR', { type: 'dateTimeField' });
console.log(frLabels.of('year'));
// "année"
console.log(frLabels.of('month'));
// "mois"
console.log(frLabels.of('day'));
// "jour"
console.log(frLabels.of('hour'));
// "heure"
console.log(frLabels.of('minute'));
// "minute"
// Étiquettes en japonais
const jaLabels = new Intl.DisplayNames('ja-JP', { type: 'dateTimeField' });
console.log(jaLabels.of('year'));
// "年"
console.log(jaLabels.of('month'));
// "月"
console.log(jaLabels.of('day'));
// "日"
console.log(jaLabels.of('hour'));
// "時"
console.log(jaLabels.of('minute'));
// "分"
Chaque locale fournit des étiquettes dans sa propre langue et son propre script.
Codes de champ de date et d'heure disponibles
L'API Intl.DisplayNames prend en charge ces codes de champ.
const labels = new Intl.DisplayNames('en-US', { type: 'dateTimeField' });
console.log(labels.of('era'));
// "era"
console.log(labels.of('year'));
// "year"
console.log(labels.of('quarter'));
// "quarter"
console.log(labels.of('month'));
// "month"
console.log(labels.of('weekOfYear'));
// "week"
console.log(labels.of('weekday'));
// "day of the week"
console.log(labels.of('day'));
// "day"
console.log(labels.of('dayPeriod'));
// "AM/PM"
console.log(labels.of('hour'));
// "hour"
console.log(labels.of('minute'));
// "minute"
console.log(labels.of('second'));
// "second"
console.log(labels.of('timeZoneName'));
// "time zone"
Utilisez ces codes pour obtenir des libellés pour n'importe quel composant de date ou d'heure dont votre interface a besoin.
Obtenir les noms de mois localisés
L'API Intl.DateTimeFormat fournit des noms de mois pour remplir les menus déroulants et les listes de sélection. Créez un formateur avec l'option month définie sur "long", puis formatez les dates représentant chaque mois.
function getMonthNames(locale) {
const formatter = new Intl.DateTimeFormat(locale, {
month: 'long',
timeZone: 'UTC'
});
const months = [];
for (let month = 0; month < 12; month++) {
const date = new Date(Date.UTC(2000, month, 1));
months.push(formatter.format(date));
}
return months;
}
console.log(getMonthNames('en-US'));
// ["January", "February", "March", "April", "May", "June",
// "July", "August", "September", "October", "November", "December"]
La fonction crée des dates pour chaque mois de l'année et les formate pour extraire le nom du mois. Définir timeZone: 'UTC' garantit des résultats cohérents dans tous les fuseaux horaires.
Vous pouvez obtenir les noms des mois dans n'importe quelle langue.
console.log(getMonthNames('es-ES'));
// ["enero", "febrero", "marzo", "abril", "mayo", "junio",
// "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"]
console.log(getMonthNames('fr-FR'));
// ["janvier", "février", "mars", "avril", "mai", "juin",
// "juillet", "août", "septembre", "octobre", "novembre", "décembre"]
console.log(getMonthNames('ja-JP'));
// ["1月", "2月", "3月", "4月", "5月", "6月",
// "7月", "8月", "9月", "10月", "11月", "12月"]
Chaque locale formate les noms des mois selon ses propres conventions.
Contrôler la longueur du nom du mois
L'option month accepte différentes valeurs qui contrôlent la longueur des noms de mois.
La valeur "long" renvoie les noms de mois complets.
const longFormatter = new Intl.DateTimeFormat('en-US', {
month: 'long',
timeZone: 'UTC'
});
const date = new Date(Date.UTC(2000, 0, 1));
console.log(longFormatter.format(date));
// "January"
La valeur "short" renvoie les noms de mois abrégés.
const shortFormatter = new Intl.DateTimeFormat('en-US', {
month: 'short',
timeZone: 'UTC'
});
console.log(shortFormatter.format(date));
// "Jan"
La valeur "narrow" renvoie les noms de mois les plus courts possibles, généralement une seule lettre.
const narrowFormatter = new Intl.DateTimeFormat('en-US', {
month: 'narrow',
timeZone: 'UTC'
});
console.log(narrowFormatter.format(date));
// "J"
Utilisez "narrow" avec précaution, car plusieurs mois peuvent partager la même lettre. En anglais, janvier, juin et juillet produisent tous "J".
Obtenir les noms de jours de la semaine localisés
Utilisez le même modèle pour obtenir les noms des jours de la semaine. Définissez l'option weekday pour contrôler le format.
function getWeekdayNames(locale, format = 'long') {
const formatter = new Intl.DateTimeFormat(locale, {
weekday: format,
timeZone: 'UTC'
});
const weekdays = [];
// Commencer par un dimanche (le 2 janvier 2000 était un dimanche)
for (let day = 0; day < 7; day++) {
const date = new Date(Date.UTC(2000, 0, 2 + day));
weekdays.push(formatter.format(date));
}
return weekdays;
}
console.log(getWeekdayNames('en-US'));
// ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
console.log(getWeekdayNames('en-US', 'short'));
// ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
console.log(getWeekdayNames('en-US', 'narrow'));
// ["S", "M", "T", "W", "T", "F", "S"]
Vous pouvez obtenir les noms des jours de la semaine dans n'importe quelle langue.
console.log(getWeekdayNames('es-ES'));
// ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"]
console.log(getWeekdayNames('fr-FR'));
// ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"]
console.log(getWeekdayNames('ja-JP'));
// ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"]
Différentes locales peuvent commencer la semaine par différents jours. Cette fonction renvoie toujours les jours de dimanche à samedi dans l'ordre.
Obtenir des libellés de période localisés
Les libellés de période sont les indicateurs AM et PM utilisés avec l'heure au format 12 heures. Utilisez formatToParts() pour extraire ces libellés.
function getPeriodLabels(locale) {
const formatter = new Intl.DateTimeFormat(locale, {
hour: 'numeric',
hour12: true,
timeZone: 'UTC'
});
const amDate = new Date(Date.UTC(2000, 0, 1, 0, 0, 0));
const pmDate = new Date(Date.UTC(2000, 0, 1, 12, 0, 0));
const amParts = formatter.formatToParts(amDate);
const pmParts = formatter.formatToParts(pmDate);
const am = amParts.find(part => part.type === 'dayPeriod').value;
const pm = pmParts.find(part => part.type === 'dayPeriod').value;
return { am, pm };
}
console.log(getPeriodLabels('en-US'));
// { am: "AM", pm: "PM" }
console.log(getPeriodLabels('es-ES'));
// { am: "a. m.", pm: "p. m." }
console.log(getPeriodLabels('fr-FR'));
// { am: "AM", pm: "PM" }
console.log(getPeriodLabels('ja-JP'));
// { am: "午前", pm: "午後" }
La méthode formatToParts() renvoie un tableau d'objets représentant chaque partie de l'heure formatée. L'objet avec type: "dayPeriod" contient le libellé AM ou PM.
Certaines locales utilisent l'heure au format 24 heures par défaut et n'incluent pas de libellés de période. Vous pouvez forcer l'heure au format 12 heures avec l'option hour12: true.
Construire un formulaire de date entièrement localisé
Combinez toutes ces techniques pour créer un formulaire de saisie de date entièrement localisé.
function createDateForm(locale) {
const fieldLabels = new Intl.DisplayNames(locale, { type: 'dateTimeField' });
const monthNames = getMonthNames(locale);
const currentYear = new Date().getFullYear();
return {
monthLabel: fieldLabels.of('month'),
months: monthNames.map((name, index) => ({
value: index + 1,
label: name
})),
dayLabel: fieldLabels.of('day'),
yearLabel: fieldLabels.of('year'),
yearPlaceholder: currentYear
};
}
// Fonction auxiliaire de l'exemple précédent
function getMonthNames(locale) {
const formatter = new Intl.DateTimeFormat(locale, {
month: 'long',
timeZone: 'UTC'
});
const months = [];
for (let month = 0; month < 12; month++) {
const date = new Date(Date.UTC(2000, month, 1));
months.push(formatter.format(date));
}
return months;
}
const enForm = createDateForm('en-US');
console.log(enForm.monthLabel);
// "month"
console.log(enForm.months[0]);
// { value: 1, label: "January" }
console.log(enForm.dayLabel);
// "day"
console.log(enForm.yearLabel);
// "year"
const esForm = createDateForm('es-ES');
console.log(esForm.monthLabel);
// "mes"
console.log(esForm.months[0]);
// { value: 1, label: "enero" }
console.log(esForm.dayLabel);
// "día"
console.log(esForm.yearLabel);
// "año"
Cette structure fournit tout ce qui est nécessaire pour afficher un formulaire de date localisé en HTML.
function renderDateForm(locale) {
const form = createDateForm(locale);
return `
<div class="date-form">
<div class="form-field">
<label>${form.monthLabel}</label>
<select name="month">
${form.months.map(month =>
`<option value="${month.value}">${month.label}</option>`
).join('')}
</select>
</div>
<div class="form-field">
<label>${form.dayLabel}</label>
<input type="number" name="day" min="1" max="31" />
</div>
<div class="form-field">
<label>${form.yearLabel}</label>
<input type="number" name="year" placeholder="${form.yearPlaceholder}" />
</div>
</div>
`;
}
console.log(renderDateForm('en-US'));
// Affiche un formulaire avec des libellés et des noms de mois en anglais
console.log(renderDateForm('fr-FR'));
// Affiche un formulaire avec des libellés et des noms de mois en français
Le formulaire s'adapte automatiquement à n'importe quelle locale que vous spécifiez.
Créer un formulaire d'heure localisé
Appliquez la même approche pour créer un formulaire de saisie d'heure avec des sélecteurs d'heure, de minute et de période.
function createTimeForm(locale) {
const fieldLabels = new Intl.DisplayNames(locale, { type: 'dateTimeField' });
const periods = getPeriodLabels(locale);
const hours = [];
for (let hour = 1; hour <= 12; hour++) {
hours.push({ value: hour, label: hour.toString() });
}
const minutes = [];
for (let minute = 0; minute < 60; minute += 5) {
minutes.push({
value: minute,
label: minute.toString().padStart(2, '0')
});
}
return {
hourLabel: fieldLabels.of('hour'),
hours: hours,
minuteLabel: fieldLabels.of('minute'),
minutes: minutes,
periodLabel: fieldLabels.of('dayPeriod'),
periods: [
{ value: 'am', label: periods.am },
{ value: 'pm', label: periods.pm }
]
};
}
// Fonction auxiliaire de l'exemple précédent
function getPeriodLabels(locale) {
const formatter = new Intl.DateTimeFormat(locale, {
hour: 'numeric',
hour12: true,
timeZone: 'UTC'
});
const amDate = new Date(Date.UTC(2000, 0, 1, 0, 0, 0));
const pmDate = new Date(Date.UTC(2000, 0, 1, 12, 0, 0));
const amParts = formatter.formatToParts(amDate);
const pmParts = formatter.formatToParts(pmDate);
const am = amParts.find(part => part.type === 'dayPeriod').value;
const pm = pmParts.find(part => part.type === 'dayPeriod').value;
return { am, pm };
}
const enTime = createTimeForm('en-US');
console.log(enTime.hourLabel);
// "hour"
console.log(enTime.minuteLabel);
// "minute"
console.log(enTime.periodLabel);
// "AM/PM"
console.log(enTime.periods);
// [{ value: "am", label: "AM" }, { value: "pm", label: "PM" }]
const jaTime = createTimeForm('ja-JP');
console.log(jaTime.hourLabel);
// "時"
console.log(jaTime.minuteLabel);
// "分"
console.log(jaTime.periodLabel);
// "午前/午後"
console.log(jaTime.periods);
// [{ value: "am", label: "午前" }, { value: "pm", label: "午後" }]
Cela fournit toutes les données nécessaires pour afficher un sélecteur d'heure localisé.
Quand utiliser les libellés de champs de date et d'heure
Les libellés de champs de date et d'heure apparaissent dans plusieurs types d'interfaces.
Sélecteurs de date et d'heure personnalisés
Utilisez des libellés localisés lors de la création de sélecteurs de date, de widgets de calendrier ou de sélecteurs d'heure.
const locale = navigator.language;
const labels = new Intl.DisplayNames(locale, { type: 'dateTimeField' });
const datePicker = {
yearLabel: labels.of('year'),
monthLabel: labels.of('month'),
dayLabel: labels.of('day')
};
Libellés de champs de formulaire
Appliquez des libellés aux champs de formulaire standard pour les données de date et d'heure.
const labels = new Intl.DisplayNames('en-US', { type: 'dateTimeField' });
document.querySelector('#birthdate-month-label').textContent =
labels.of('month');
document.querySelector('#birthdate-year-label').textContent =
labels.of('year');
Libellés d'accessibilité
Fournissez des libellés ARIA localisés pour les lecteurs d'écran et les technologies d'assistance.
const locale = navigator.language;
const labels = new Intl.DisplayNames(locale, { type: 'dateTimeField' });
const input = document.querySelector('#date-input');
input.setAttribute('aria-label', labels.of('year'));
En-têtes de tableaux de données
Étiquetez les colonnes dans les tableaux qui affichent des composants de date et d'heure.
const labels = new Intl.DisplayNames('en-US', { type: 'dateTimeField' });
const table = `
<table>
<thead>
<tr>
<th>${labels.of('year')}</th>
<th>${labels.of('month')}</th>
<th>${labels.of('day')}</th>
</tr>
</thead>
</table>
`;
Compatibilité des navigateurs
L'API Intl.DisplayNames avec type: "dateTimeField" est prise en charge depuis mars 2022 dans les principaux navigateurs.
Chrome et Edge la prennent en charge à partir de la version 99. Firefox la prend en charge à partir de la version 99. Safari la prend en charge à partir de la version 15.4.
Vous pouvez vérifier si la fonctionnalité est disponible avant de l'utiliser.
function supportsDateTimeFieldLabels() {
try {
const labels = new Intl.DisplayNames('en', { type: 'dateTimeField' });
labels.of('year');
return true;
} catch (error) {
return false;
}
}
if (supportsDateTimeFieldLabels()) {
const labels = new Intl.DisplayNames('en-US', { type: 'dateTimeField' });
console.log(labels.of('month'));
} else {
console.log('month'); // Fallback to English
}
Pour les navigateurs plus anciens, vous devez fournir des libellés de secours. Créez un objet de mappage simple pour les champs courants.
const fallbackLabels = {
en: {
year: 'year',
month: 'month',
day: 'day',
hour: 'hour',
minute: 'minute',
second: 'second'
},
es: {
year: 'año',
month: 'mes',
day: 'día',
hour: 'hora',
minute: 'minuto',
second: 'segundo'
},
fr: {
year: 'année',
month: 'mois',
day: 'jour',
hour: 'heure',
minute: 'minute',
second: 'seconde'
}
};
function getFieldLabel(field, locale) {
if (supportsDateTimeFieldLabels()) {
const labels = new Intl.DisplayNames(locale, { type: 'dateTimeField' });
return labels.of(field);
}
const language = locale.split('-')[0];
return fallbackLabels[language]?.[field] || fallbackLabels.en[field];
}
console.log(getFieldLabel('month', 'es-ES'));
// "mes" (from API if supported, from fallback otherwise)
Cela garantit que vos formulaires fonctionnent dans tous les navigateurs tout en profitant de la localisation native lorsqu'elle est disponible.
L'API Intl.DateTimeFormat pour obtenir les noms des mois et des jours de la semaine bénéficie d'une prise en charge plus large, remontant à Internet Explorer 11 et à tous les navigateurs modernes. Vous pouvez l'utiliser sans détection de fonctionnalité dans la plupart des cas.