Comprehensive internationalization support for React applications with locale-aware hooks and utilities
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Numeric formatting and list presentation for different locales and cultural contexts with automatic locale updates and performance caching.
Provides localized number formatting for the current locale with support for currency, percentages, and custom number styles.
/**
* Provides localized number formatting for the current locale. Automatically updates when the locale changes,
* and handles caching of the number formatter for performance.
* @param options - Formatting options from @internationalized/number
* @returns Intl.NumberFormat instance
*/
function useNumberFormatter(options?: NumberFormatOptions): Intl.NumberFormat;
type NumberFormatOptions = Intl.NumberFormatOptions;Usage Examples:
import { useNumberFormatter, I18nProvider } from "@react-aria/i18n";
// Basic number formatting
function NumberDisplay() {
const formatter = useNumberFormatter();
return <p>{formatter.format(1234567.89)}</p>;
// US English: "1,234,567.89"
// German: "1.234.567,89"
// French: "1 234 567,89"
}
// Currency formatting
function CurrencyDisplay() {
const formatter = useNumberFormatter({
style: "currency",
currency: "USD"
});
return <p>{formatter.format(1299.99)}</p>;
// US English: "$1,299.99"
// UK English: "US$1,299.99"
}
// Percentage formatting
function PercentageDisplay() {
const formatter = useNumberFormatter({
style: "percent",
minimumFractionDigits: 1
});
return <p>{formatter.format(0.1534)}</p>;
// "15.3%"
}
// Unit formatting
function UnitDisplay() {
const formatter = useNumberFormatter({
style: "unit",
unit: "kilometer-per-hour",
unitDisplay: "short"
});
return <p>{formatter.format(65)}</p>;
// "65 km/h"
}
// Custom decimal and grouping options
function PrecisionNumberDisplay() {
const formatter = useNumberFormatter({
minimumFractionDigits: 2,
maximumFractionDigits: 4,
useGrouping: true
});
return <p>{formatter.format(1234.5)}</p>;
// "1,234.50"
}The Intl.NumberFormat provides additional methods for advanced formatting needs.
interface Intl.NumberFormat {
/** Format a number to a string */
format(value: number): string;
/** Format a number to an array of parts with type information */
formatToParts(value: number): Intl.NumberFormatPart[];
/** Format a range between two numbers */
formatRange(start: number, end: number): string;
/** Format a range to parts */
formatRangeToParts(start: number, end: number): Intl.NumberFormatPart[];
/** Get resolved formatting options */
resolvedOptions(): Intl.ResolvedNumberFormatOptions;
}Advanced Usage Examples:
function AdvancedNumberFormatting() {
const formatter = useNumberFormatter({
style: "currency",
currency: "EUR",
minimumFractionDigits: 2
});
const value = 1234.56;
const startValue = 100;
const endValue = 200;
return (
<div>
{/* Basic formatting */}
<p>Price: {formatter.format(value)}</p>
{/* Parts formatting for custom styling */}
<p>
Styled: {formatter.formatToParts(value).map((part, i) => (
<span key={i} className={`number-${part.type}`}>
{part.value}
</span>
))}
</p>
{/* Range formatting */}
<p>Range: {formatter.formatRange(startValue, endValue)}</p>
{/* Resolved options */}
<p>Currency: {formatter.resolvedOptions().currency}</p>
</div>
);
}Provides localized list formatting for arrays with proper conjunction and disjunction support.
/**
* Provides localized list formatting for the current locale. Automatically updates when the locale changes,
* and handles caching of the list formatter for performance.
* @param options - Formatting options for list presentation
* @returns Intl.ListFormat instance
*/
function useListFormatter(options?: Intl.ListFormatOptions): Intl.ListFormat;
interface Intl.ListFormatOptions {
/** The locale matching algorithm to use */
localeMatcher?: "best fit" | "lookup";
/** The type of list */
type?: "conjunction" | "disjunction" | "unit";
/** The style of the list */
style?: "long" | "short" | "narrow";
}Usage Examples:
import { useListFormatter, I18nProvider } from "@react-aria/i18n";
// Basic list formatting (conjunction - "and")
function BasicListDisplay() {
const formatter = useListFormatter({
style: "long",
type: "conjunction"
});
const items = ["apples", "oranges", "bananas"];
return <p>{formatter.format(items)}</p>;
// English: "apples, oranges, and bananas"
// Spanish: "apples, oranges y bananas"
}
// Disjunction list formatting ("or")
function DisjunctionListDisplay() {
const formatter = useListFormatter({
style: "long",
type: "disjunction"
});
const options = ["red", "blue", "green"];
return <p>Choose: {formatter.format(options)}</p>;
// English: "red, blue, or green"
}
// Unit list formatting (no conjunctions)
function UnitListDisplay() {
const formatter = useListFormatter({
style: "short",
type: "unit"
});
const measurements = ["5 ft", "10 in"];
return <p>{formatter.format(measurements)}</p>;
// "5 ft, 10 in"
}
// Different styles comparison
function ListStyleComparison() {
const longFormatter = useListFormatter({ style: "long" });
const shortFormatter = useListFormatter({ style: "short" });
const narrowFormatter = useListFormatter({ style: "narrow" });
const items = ["first", "second", "third"];
return (
<div>
<p>Long: {longFormatter.format(items)}</p>
<p>Short: {shortFormatter.format(items)}</p>
<p>Narrow: {narrowFormatter.format(items)}</p>
</div>
);
}
// Locale-specific list formatting
function LocaleSpecificLists() {
const items = ["JavaScript", "TypeScript", "React"];
return (
<div>
<I18nProvider locale="en-US">
<ListDisplay items={items} />
</I18nProvider>
<I18nProvider locale="de-DE">
<ListDisplay items={items} />
</I18nProvider>
<I18nProvider locale="ja-JP">
<ListDisplay items={items} />
</I18nProvider>
</div>
);
}
function ListDisplay({ items }: { items: string[] }) {
const formatter = useListFormatter();
return <p>{formatter.format(items)}</p>;
}Additional methods available on the ListFormat instance.
interface Intl.ListFormat {
/** Format an array of strings to a localized list string */
format(list: string[]): string;
/** Format an array to parts with type information */
formatToParts(list: string[]): Intl.ListFormatPart[];
/** Get resolved formatting options */
resolvedOptions(): Intl.ResolvedListFormatOptions;
}Advanced List Formatting:
function AdvancedListFormatting() {
const formatter = useListFormatter({
style: "long",
type: "conjunction"
});
const items = ["red", "green", "blue"];
return (
<div>
{/* Basic formatting */}
<p>Colors: {formatter.format(items)}</p>
{/* Parts formatting for custom styling */}
<p>
Styled: {formatter.formatToParts(items).map((part, i) => (
<span key={i} className={`list-${part.type}`}>
{part.value}
</span>
))}
</p>
{/* Options inspection */}
<p>Style: {formatter.resolvedOptions().style}</p>
</div>
);
}Install with Tessl CLI
npx tessl i tessl/npm-react-aria--i18n