Comment diviser la sortie formatée en morceaux pour le style
Utilisez formatToParts() pour accéder aux composants individuels de la sortie formatée pour un style personnalisé
Introduction
La méthode format() des formateurs JavaScript renvoie des chaînes complètes comme "$1,234.56" ou "January 15, 2025". Cela fonctionne bien pour un affichage simple, mais vous ne pouvez pas styliser différemment les parties individuelles. Vous ne pouvez pas mettre en gras le symbole de devise, colorer différemment le nom du mois, ou appliquer un balisage personnalisé à des composants spécifiques.
JavaScript fournit la méthode formatToParts() pour résoudre ce problème. Au lieu de renvoyer une seule chaîne, elle renvoie un tableau d'objets, chacun représentant une partie de la sortie formatée. Chaque partie a un type comme currency, month, ou element, et une valeur contenant la chaîne réelle. Vous pouvez ensuite traiter ces parties pour appliquer un style personnalisé, construire des mises en page complexes, ou intégrer du contenu formaté dans des interfaces utilisateur riches.
La méthode formatToParts() est disponible sur plusieurs formateurs Intl, notamment NumberFormat, DateTimeFormat, ListFormat, RelativeTimeFormat, et DurationFormat. Cela en fait un modèle cohérent pour toute la mise en forme d'internationalisation en JavaScript.
Pourquoi les chaînes formatées ne peuvent pas être facilement stylisées
Lorsque vous recevez une chaîne formatée comme "$1,234.56", vous ne pouvez pas facilement identifier où se termine le symbole de devise et où commence le nombre. Différentes locales placent les symboles à différentes positions. Certaines locales utilisent différents séparateurs. L'analyse fiable de ces chaînes nécessite une logique complexe qui duplique les règles de formatage déjà implémentées dans l'API Intl.
Considérez un tableau de bord qui affiche des montants monétaires avec le symbole de devise dans une couleur différente. Avec format(), vous devriez :
- Détecter quels caractères constituent le symbole de devise
- Tenir compte des espaces entre le symbole et le nombre
- Gérer les différentes positions des symboles selon les locales
- Analyser la chaîne avec précaution pour éviter de casser le nombre
Cette approche est fragile et sujette aux erreurs. Tout changement dans les règles de formatage des locales brise votre logique d'analyse.
Le même problème existe pour les dates, les listes et autres sorties formatées. Vous ne pouvez pas analyser de manière fiable les chaînes formatées pour identifier les composants sans réimplémenter les règles de formatage spécifiques à la locale.
La méthode formatToParts() élimine ce problème en fournissant les composants séparément. Vous recevez des données structurées qui vous indiquent exactement quelle partie est laquelle, quelle que soit la locale.
Comment fonctionne formatToParts
La méthode formatToParts() fonctionne de manière identique à format() à l'exception de sa valeur de retour. Vous créez un formateur avec les mêmes options, puis appelez formatToParts() au lieu de format().
La méthode renvoie un tableau d'objets. Chaque objet contient deux propriétés :
type: identifie ce que la partie représente, commecurrency,month, ouliteralvalue: contient la chaîne réelle pour cette partie
Les parties apparaissent dans le même ordre que dans la sortie formatée. Vous pouvez vérifier cela en joignant toutes les valeurs ensemble, ce qui produit exactement la même sortie que l'appel à format().
Ce modèle est cohérent pour tous les formateurs qui prennent en charge formatToParts(). Les types de parties spécifiques varient selon le formateur, mais la structure est toujours la même.
Diviser les nombres formatés en parties
Le formateur NumberFormat fournit formatToParts() pour décomposer les nombres formatés. Cela fonctionne pour les nombres de base, les devises, les pourcentages et autres styles numériques.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
const parts = formatter.formatToParts(1234.56);
console.log(parts);
Cela produit un tableau d'objets :
[
{ type: "currency", value: "$" },
{ type: "integer", value: "1" },
{ type: "group", value: "," },
{ type: "integer", value: "234" },
{ type: "decimal", value: "." },
{ type: "fraction", value: "56" }
]
Chaque objet identifie ce que la partie représente et fournit sa valeur. Le type currency représente le symbole de devise. Le type integer représente les chiffres entiers. Le type group représente le séparateur des milliers. Le type decimal représente le point décimal. Le type fraction représente les chiffres après la décimale.
Vous pouvez vérifier que les parties correspondent à la sortie formatée :
const formatted = parts.map(part => part.value).join("");
console.log(formatted);
// Sortie : "$1,234.56"
Les parties concaténées produisent exactement la même sortie que l'appel à format().
Styliser les symboles de devise dans les nombres formatés
Le cas d'utilisation principal de formatToParts() est d'appliquer différents styles à différents composants. Vous pouvez traiter le tableau de parties pour envelopper des types spécifiques dans des éléments HTML.
Rendre le symbole de devise en gras :
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);
// Résultat : "<strong>$</strong>1,234.56"
Cette approche fonctionne pour n'importe quel langage de balisage. Vous pouvez générer du HTML, du JSX ou tout autre format en traitant le tableau de parties.
Styler différemment les parties décimales :
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);
// Résultat : "1,234<span class="text-gray-500">.50</span>"
Ce modèle est courant dans les affichages de prix où la partie décimale apparaît plus petite ou plus claire.
Diviser les dates formatées en parties
Le formateur DateTimeFormat fournit formatToParts() pour décomposer les dates et heures formatées.
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);
Cela produit un tableau d'objets :
[
{ type: "month", value: "January" },
{ type: "literal", value: " " },
{ type: "day", value: "15" },
{ type: "literal", value: ", " },
{ type: "year", value: "2025" }
]
Le type month représente le nom ou le numéro du mois. Le type day représente le jour du mois. Le type year représente l'année. Le type literal représente les espaces, la ponctuation ou autre texte inséré par le formateur.
Styliser les noms de mois dans les dates formatées
Vous pouvez appliquer un style personnalisé aux composants de date en utilisant le même modèle que pour les nombres.
Rendre le nom du mois en gras :
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);
// Résultat : "<strong>January</strong> 15, 2025"
Styliser plusieurs composants de date :
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);
// Résultat : "<span class="font-bold">Wednesday</span>, <span class="text-blue-600">January</span> 15, <span class="text-gray-500">2025</span>"
Ce contrôle granulaire permet un style précis pour chaque composant.
Diviser les listes formatées en parties
Le formateur ListFormat fournit formatToParts() pour décomposer les listes formatées.
const formatter = new Intl.ListFormat("en-US", {
style: "long",
type: "conjunction"
});
const items = ["apples", "oranges", "bananas"];
const parts = formatter.formatToParts(items);
console.log(parts);
Cela produit un tableau d'objets :
[
{ type: "element", value: "apples" },
{ type: "literal", value: ", " },
{ type: "element", value: "oranges" },
{ type: "literal", value: ", and " },
{ type: "element", value: "bananas" }
]
Le type element représente chaque élément de la liste. Le type literal représente les séparateurs et les conjonctions ajoutés par le formateur.
Styliser individuellement les éléments de liste
Vous pouvez appliquer un style personnalisé aux éléments de liste en utilisant le même modèle.
Rendre les éléments de liste en gras :
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>"
Styler des éléments de liste spécifiques :
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"
Cette approche vous permet de mettre en évidence des éléments spécifiques tout en conservant un formatage correct selon les paramètres régionaux.
Diviser les temps relatifs formatés en parties
Le formateur RelativeTimeFormat fournit formatToParts() pour décomposer les expressions de temps relatif.
const formatter = new Intl.RelativeTimeFormat("en-US", {
numeric: "auto"
});
const parts = formatter.formatToParts(-1, "day");
console.log(parts);
Cela produit un tableau d'objets :
[
{ type: "literal", value: "yesterday" }
]
Pour les temps relatifs numériques :
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" }
// ]
Le type integer représente la valeur numérique. Le type literal représente l'unité de temps relatif et la direction.
Diviser les durées formatées en parties
Le formateur DurationFormat fournit formatToParts() pour décomposer les durées formatées.
const formatter = new Intl.DurationFormat("en-US", {
style: "long"
});
const parts = formatter.formatToParts({
hours: 2,
minutes: 30,
seconds: 15
});
console.log(parts);
Cela produit un tableau d'objets similaire à :
[
{ type: "integer", value: "2" },
{ type: "literal", value: " hours, " },
{ type: "integer", value: "30" },
{ type: "literal", value: " minutes, " },
{ type: "integer", value: "15" },
{ type: "literal", value: " seconds" }
]
Le type integer représente les valeurs numériques. Le type literal représente les noms d'unités et les séparateurs.
Construire du HTML à partir des parties formatées
Vous pouvez créer une fonction réutilisable qui traite les parties et applique des règles de style de manière cohérente.
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>"
Ce modèle sépare les règles de style de la logique de formatage, ce qui facilite la maintenance et la réutilisation.
Comprendre l'ordre des parties spécifiques à la locale
Le tableau des parties maintient automatiquement les règles de formatage spécifiques à la locale. Différentes locales placent les composants dans des ordres différents et utilisent des formats différents, mais formatToParts() gère ces différences.
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: "€" }
// ]
Le formatage allemand place la devise après le nombre avec un espace. Le séparateur de groupe est un point, et le séparateur décimal est une virgule. Votre code de style traite le tableau des parties de la même manière quelle que soit la locale, et le formatage s'adapte automatiquement.
Création d'affichages formatés accessibles
Vous pouvez utiliser formatToParts() pour ajouter des attributs d'accessibilité à la sortie formatée. Cela aide les lecteurs d'écran à annoncer correctement les valeurs.
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>"
Cela garantit que les lecteurs d'écran annoncent à la fois la valeur d'affichage formatée et la valeur numérique sous-jacente avec le contexte approprié.
Combinaison de formatToParts avec des composants de framework
Les frameworks modernes comme React peuvent utiliser formatToParts() pour construire des composants efficacement.
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>
);
}
Ce composant applique différents styles à différentes parties tout en maintenant un formatage approprié pour n'importe quelle locale et devise.
Quand utiliser formatToParts
Utilisez format() lorsque vous avez besoin d'une simple chaîne formatée sans personnalisation. C'est le cas courant pour la plupart des scénarios d'affichage.
Utilisez formatToParts() lorsque vous avez besoin de :
- Appliquer différents styles à différentes parties de la sortie formatée
- Construire du HTML ou JSX avec du contenu formaté
- Ajouter des attributs ou des métadonnées à des composants spécifiques
- Intégrer une sortie formatée dans des mises en page complexes
- Traiter programmatiquement une sortie formatée
- Créer des designs visuels personnalisés qui nécessitent un contrôle granulaire
La méthode formatToParts() a légèrement plus de surcharge que format() car elle crée un tableau d'objets au lieu d'une seule chaîne. Cette différence est négligeable pour les applications typiques, mais si vous formatez des milliers de valeurs par seconde, format() offre de meilleures performances.
Pour la plupart des applications, choisissez en fonction de vos besoins de style plutôt que des préoccupations de performance. Si vous n'avez pas besoin de personnaliser la sortie, utilisez format(). Si vous avez besoin d'un style ou d'un balisage personnalisé, utilisez formatToParts().
Types de parties communs entre les formateurs
Différents formateurs produisent différents types de parties, mais certains types apparaissent dans plusieurs formateurs :
literal: Espacement, ponctuation ou autre texte ajouté par le formatage. Apparaît dans les dates, nombres, listes et durées.integer: Chiffres entiers. Apparaît dans les nombres, temps relatifs et durées.decimal: Séparateur décimal. Apparaît dans les nombres.fraction: Chiffres décimaux. Apparaît dans les nombres.
Les types spécifiques aux formateurs incluent :
- Nombres :
currency,group,percentSign,minusSign,plusSign,unit,compact,exponentInteger - Dates :
weekday,era,year,month,day,hour,minute,second,dayPeriod,timeZoneName - Listes :
element - Temps relatifs : Les valeurs numériques apparaissent comme
integer, le texte apparaît commeliteral
Comprendre ces types vous aide à écrire du code de style qui traite correctement toute sortie de formateur.