Internationalize JS apps with APIs to format dates, numbers, and strings, including pluralization and handling translations.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Format relative time expressions and handle pluralization rules for different locales. Provides locale-aware relative time formatting and plural rule selection for complex grammatical patterns.
Formats relative time expressions with locale-appropriate patterns and units.
/**
* Format relative time expressions with locale-appropriate patterns
* @param config - Configuration with locale, formats, and error handler
* @param getRelativeTimeFormat - RelativeTimeFormat factory function
* @param value - Numeric value for the relative time (positive for future, negative for past)
* @param unit - Time unit for the relative expression
* @param options - Relative time formatting options including custom formats
* @returns Formatted relative time string
*/
function formatRelativeTime(
config: {
locale: string;
formats: CustomFormats;
onError: OnErrorFn;
},
getRelativeTimeFormat: Formatters['getRelativeTimeFormat'],
value: number,
unit?: Intl.RelativeTimeFormatUnit,
options?: FormatRelativeTimeOptions
): string;Usage Examples:
import { formatRelativeTime, createFormatters } from "@formatjs/intl";
const config = {
locale: 'en-US',
formats: {
relative: {
short: { numeric: 'auto', style: 'short' },
long: { numeric: 'always', style: 'long' }
}
},
onError: console.error
};
const formatters = createFormatters();
// Basic relative time formatting
const pastDay = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-1,
'day'
);
// Result: "yesterday"
const futureHour = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
2,
'hour'
);
// Result: "in 2 hours"
const pastWeek = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-1,
'week'
);
// Result: "last week"
// Different units
const minutes = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-30,
'minute'
);
// Result: "30 minutes ago"
const years = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
5,
'year'
);
// Result: "in 5 years"
// Using custom formats
const shortStyle = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-2,
'day',
{ format: 'short' }
);
// Result: "2 days ago" (style dependent)Determines the appropriate plural rule for a given number in the specified locale.
/**
* Determine appropriate plural rule for numbers in locale
* @param config - Configuration with locale and error handler
* @param getPluralRules - PluralRules factory function
* @param value - Number to determine plural rule for
* @param options - Plural rules options including ordinal/cardinal type
* @returns LDML plural rule ('zero', 'one', 'two', 'few', 'many', 'other')
*/
function formatPlural(
config: {
locale: string;
onError: OnErrorFn;
},
getPluralRules: Formatters['getPluralRules'],
value: number,
options?: FormatPluralOptions
): LDMLPluralRule;Usage Examples:
import { formatPlural, createFormatters } from "@formatjs/intl";
const config = {
locale: 'en-US',
onError: console.error
};
const formatters = createFormatters();
// Cardinal plurals (for counting)
const one = formatPlural(config, formatters.getPluralRules, 1);
// Result: "one"
const many = formatPlural(config, formatters.getPluralRules, 5);
// Result: "other"
const zero = formatPlural(config, formatters.getPluralRules, 0);
// Result: "other" (in English)
// Ordinal plurals (for ordering: 1st, 2nd, 3rd, 4th)
const first = formatPlural(config, formatters.getPluralRules, 1, {
type: 'ordinal'
});
// Result: "one"
const second = formatPlural(config, formatters.getPluralRules, 2, {
type: 'ordinal'
});
// Result: "two"
const third = formatPlural(config, formatters.getPluralRules, 3, {
type: 'ordinal'
});
// Result: "few"
const fourth = formatPlural(config, formatters.getPluralRules, 4, {
type: 'ordinal'
});
// Result: "other"Options for controlling relative time formatting behavior.
type FormatRelativeTimeOptions = Omit<Intl.RelativeTimeFormatOptions, 'localeMatcher'> & {
/** Named format reference from custom formats */
format?: string;
};
interface RelativeTimeFormatOptions {
/** Whether to use numeric output (always) or natural language (auto) */
numeric?: 'always' | 'auto';
/** Formatting style affecting verbosity */
style?: 'long' | 'short' | 'narrow';
}Usage Examples:
// Numeric vs automatic formatting
const numericAlways = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-1,
'day',
{ numeric: 'always' }
);
// Result: "1 day ago"
const numericAuto = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-1,
'day',
{ numeric: 'auto' }
);
// Result: "yesterday"
// Different styles
const longStyle = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-2,
'hour',
{ style: 'long' }
);
// Result: "2 hours ago"
const shortStyle = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-2,
'hour',
{ style: 'short' }
);
// Result: "2 hr. ago"
const narrowStyle = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-2,
'hour',
{ style: 'narrow' }
);
// Result: "2h ago"Options for controlling plural rule selection.
type FormatPluralOptions = Omit<Intl.PluralRulesOptions, 'localeMatcher'>;
interface PluralRulesOptions {
/** Type of plural rules: cardinal for counting, ordinal for ordering */
type?: 'cardinal' | 'ordinal';
}
type LDMLPluralRule = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other';Usage Examples:
// Cardinal vs ordinal plurals
const cardinalOne = formatPlural(config, formatters.getPluralRules, 21, {
type: 'cardinal'
});
// Result: "other" (21 items)
const ordinalOne = formatPlural(config, formatters.getPluralRules, 21, {
type: 'ordinal'
});
// Result: "one" (21st place)
const cardinal22 = formatPlural(config, formatters.getPluralRules, 22, {
type: 'cardinal'
});
// Result: "other"
const ordinal22 = formatPlural(config, formatters.getPluralRules, 22, {
type: 'ordinal'
});
// Result: "two" (22nd place)Comprehensive support for all relative time units.
Usage Examples:
// All standard time units
const second = formatRelativeTime(config, formatters.getRelativeTimeFormat, -30, 'second');
// Result: "30 seconds ago"
const minute = formatRelativeTime(config, formatters.getRelativeTimeFormat, -15, 'minute');
// Result: "15 minutes ago"
const hour = formatRelativeTime(config, formatters.getRelativeTimeFormat, -3, 'hour');
// Result: "3 hours ago"
const day = formatRelativeTime(config, formatters.getRelativeTimeFormat, 7, 'day');
// Result: "in 7 days"
const week = formatRelativeTime(config, formatters.getRelativeTimeFormat, 2, 'week');
// Result: "in 2 weeks"
const month = formatRelativeTime(config, formatters.getRelativeTimeFormat, -6, 'month');
// Result: "6 months ago"
const quarter = formatRelativeTime(config, formatters.getRelativeTimeFormat, 1, 'quarter');
// Result: "in 1 quarter"
const year = formatRelativeTime(config, formatters.getRelativeTimeFormat, -10, 'year');
// Result: "10 years ago"
// Special cases with auto numeric
const yesterday = formatRelativeTime(config, formatters.getRelativeTimeFormat, -1, 'day', {
numeric: 'auto'
});
// Result: "yesterday"
const tomorrow = formatRelativeTime(config, formatters.getRelativeTimeFormat, 1, 'day', {
numeric: 'auto'
});
// Result: "tomorrow"
const now = formatRelativeTime(config, formatters.getRelativeTimeFormat, 0, 'second', {
numeric: 'auto'
});
// Result: "now"Different locales have different relative time patterns and plural rules.
Usage Examples:
// Relative time in different locales
const englishPast = formatRelativeTime(
{ ...config, locale: 'en-US' },
formatters.getRelativeTimeFormat,
-2,
'day'
);
// Result: "2 days ago"
const spanishPast = formatRelativeTime(
{ ...config, locale: 'es-ES' },
formatters.getRelativeTimeFormat,
-2,
'day'
);
// Result: "hace 2 días"
const frenchPast = formatRelativeTime(
{ ...config, locale: 'fr-FR' },
formatters.getRelativeTimeFormat,
-2,
'day'
);
// Result: "il y a 2 jours"
const germanPast = formatRelativeTime(
{ ...config, locale: 'de-DE' },
formatters.getRelativeTimeFormat,
-2,
'day'
);
// Result: "vor 2 Tagen"
// Complex plural rules in different locales
const polishPlurals = [1, 2, 5, 21, 22, 25].map(n =>
formatPlural(
{ ...config, locale: 'pl-PL' },
formatters.getPluralRules,
n
)
);
// Result: ["one", "few", "many", "many", "few", "many"]
const russianPlurals = [1, 2, 5, 21, 22, 25].map(n =>
formatPlural(
{ ...config, locale: 'ru-RU' },
formatters.getPluralRules,
n
)
);
// Result: ["one", "few", "many", "one", "few", "many"]
// Arabic has six plural forms
const arabicPlurals = [0, 1, 2, 3, 11, 100].map(n =>
formatPlural(
{ ...config, locale: 'ar-SA' },
formatters.getPluralRules,
n
)
);
// Result: ["zero", "one", "two", "few", "many", "other"]Complex relative time scenarios and edge cases.
Usage Examples:
// Fractional values (rounded by the formatter)
const fractionalHour = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-1.5,
'hour'
);
// Result: "1 hour ago" (rounded)
// Very large values
const centuriesAgo = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-200,
'year'
);
// Result: "200 years ago"
// Edge cases with zero
const zeroMinutes = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
0,
'minute',
{ numeric: 'auto' }
);
// Result: "now"
const zeroMinutesNumeric = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
0,
'minute',
{ numeric: 'always' }
);
// Result: "in 0 minutes"
// Default unit (when not specified)
const defaultUnit = formatRelativeTime(
config,
formatters.getRelativeTimeFormat,
-5
// Default unit is 'second'
);
// Result: "5 seconds ago"Integration with ICU MessageFormat for complex pluralization.
Usage Examples:
// Using formatPlural result in message formatting
const count = 5;
const pluralRule = formatPlural(config, formatters.getPluralRules, count);
const messages = {
zero: 'No items',
one: 'One item',
two: 'Two items',
few: 'A few items',
many: 'Many items',
other: `${count} items`
};
const message = messages[pluralRule];
// Result: "5 items"
// Complex plural patterns with ICU MessageFormat
const complexMessage = intl.formatMessage(
{
id: 'item.count',
defaultMessage: `{count, plural,
=0 {No items}
=1 {One item}
=2 {Two items}
few {A few items (#)}
many {Many items (#)}
other {# items}
}`
},
{ count: 5 }
);
// Ordinal plurals for rankings
const position = 23;
const ordinalRule = formatPlural(config, formatters.getPluralRules, position, {
type: 'ordinal'
});
const ordinalSuffixes = {
one: 'st',
two: 'nd',
few: 'rd',
other: 'th'
};
const ordinalText = `${position}${ordinalSuffixes[ordinalRule]}`;
// Result: "23rd"Define reusable relative time format configurations.
Usage Examples:
const intl = createIntl({
locale: 'en-US',
formats: {
relative: {
short: {
numeric: 'auto',
style: 'short'
},
verbose: {
numeric: 'always',
style: 'long'
},
compact: {
numeric: 'auto',
style: 'narrow'
}
}
}
});
// Use custom formats
const shortFormat = intl.formatRelativeTime(-1, 'day', { format: 'short' });
// Result: "1 day ago" or "yesterday" (depending on implementation)
const verboseFormat = intl.formatRelativeTime(-1, 'day', { format: 'verbose' });
// Result: "1 day ago"
const compactFormat = intl.formatRelativeTime(-2, 'hour', { format: 'compact' });
// Result: "2h ago"When using createIntl, relative time and plural methods are available on the instance.
Usage Examples:
import { createIntl } from "@formatjs/intl";
const intl = createIntl({
locale: 'en-US'
});
// Instance methods
const relativeTime = intl.formatRelativeTime(-3, 'day');
// Result: "3 days ago"
const pluralRule = intl.formatPlural(5);
// Result: "other"
// Dynamic relative time calculation
const getRelativeTime = (date: Date) => {
const now = new Date();
const diffInMs = date.getTime() - now.getTime();
const diffInMinutes = Math.round(diffInMs / (1000 * 60));
if (Math.abs(diffInMinutes) < 60) {
return intl.formatRelativeTime(diffInMinutes, 'minute');
}
const diffInHours = Math.round(diffInMinutes / 60);
if (Math.abs(diffInHours) < 24) {
return intl.formatRelativeTime(diffInHours, 'hour');
}
const diffInDays = Math.round(diffInHours / 24);
return intl.formatRelativeTime(diffInDays, 'day');
};
// Usage
const pastDate = new Date(Date.now() - 2 * 60 * 60 * 1000); // 2 hours ago
const relativeText = getRelativeTime(pastDate);
// Result: "2 hours ago"