or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

date-time-formatting.mddisplay-name-formatting.mdindex.mdintl-instance.mdlist-formatting.mdmessage-formatting.mdnumber-formatting.mdrelative-time-pluralization.mdutility-functions.md
tile.json

relative-time-pluralization.mddocs/

Relative Time and Pluralization

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.

Capabilities

formatRelativeTime Function

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)

formatPlural Function

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"

FormatRelativeTimeOptions Interface

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"

FormatPluralOptions Interface

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)

Time Units and Relative Formatting

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"

Locale-Specific Relative Time and Plurals

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"]

Advanced Relative Time Patterns

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"

Plural Rules in Message Formatting

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"

Custom Relative Time Formats

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"

Integration with Intl Instance

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"