Better I18NBetter I18N

Formatting

Format dates, numbers, lists, and relative times with useFormatter

Basic Usage

import { useFormatter } from '@better-i18n/use-intl'

function ProductInfo({ price, date }) {
  const format = useFormatter()

  return (
    <div>
      <span>{format.number(price, { style: 'currency', currency: 'USD' })}</span>
      <time>{format.dateTime(date, { dateStyle: 'medium' })}</time>
    </div>
  )
}

Available Methods

MethodDescription
dateTime(date, options)Format a date/time
number(value, options)Format a number
list(items, options)Format a list of items
relativeTime(date, options)Format relative time (e.g., "2 hours ago")

Date & Time Formatting

Date Styles

const format = useFormatter()

// Short date
format.dateTime(new Date(), { dateStyle: 'short' })
// "1/18/26"

// Medium date
format.dateTime(new Date(), { dateStyle: 'medium' })
// "Jan 18, 2026"

// Long date
format.dateTime(new Date(), { dateStyle: 'long' })
// "January 18, 2026"

// Full date
format.dateTime(new Date(), { dateStyle: 'full' })
// "Sunday, January 18, 2026"

Time Styles

// Short time
format.dateTime(new Date(), { timeStyle: 'short' })
// "3:30 PM"

// With timezone
format.dateTime(new Date(), {
  timeStyle: 'long',
  timeZone: 'America/New_York'
})
// "3:30:00 PM EST"

Combined Date & Time

format.dateTime(new Date(), {
  dateStyle: 'medium',
  timeStyle: 'short'
})
// "Jan 18, 2026, 3:30 PM"

Custom Patterns

format.dateTime(new Date(), {
  year: 'numeric',
  month: 'long',
  day: '2-digit',
  weekday: 'short'
})
// "Sun, January 18, 2026"

Number Formatting

Basic Numbers

const format = useFormatter()

format.number(1234567.89)
// "1,234,567.89"

Currency

format.number(99.99, {
  style: 'currency',
  currency: 'USD'
})
// "$99.99"

format.number(99.99, {
  style: 'currency',
  currency: 'EUR'
})
// "€99.99"

Percentages

format.number(0.75, { style: 'percent' })
// "75%"

Compact Notation

format.number(1000000, { notation: 'compact' })
// "1M"

format.number(1234, { notation: 'compact', compactDisplay: 'long' })
// "1 thousand"

Units

format.number(100, {
  style: 'unit',
  unit: 'kilometer',
  unitDisplay: 'short'
})
// "100 km"

List Formatting

Conjunction (and)

const format = useFormatter()

format.list(['Apple', 'Banana', 'Orange'], { type: 'conjunction' })
// "Apple, Banana, and Orange"

Disjunction (or)

format.list(['Red', 'Blue', 'Green'], { type: 'disjunction' })
// "Red, Blue, or Green"

Unit Lists

format.list(['5 km', '10 km', '15 km'], { type: 'unit' })
// "5 km, 10 km, 15 km"

Relative Time

Automatic Updates

import { useFormatter, useNow } from '@better-i18n/use-intl'

function TimeAgo({ date }) {
  const format = useFormatter()
  const now = useNow({ updateInterval: 60000 }) // Update every minute

  return <time>{format.relativeTime(date, now)}</time>
}

Examples

const format = useFormatter()
const now = new Date()

// Past times
format.relativeTime(new Date(now - 60000))       // "1 minute ago"
format.relativeTime(new Date(now - 3600000))     // "1 hour ago"
format.relativeTime(new Date(now - 86400000))    // "yesterday"

// Future times
format.relativeTime(new Date(now + 86400000))    // "tomorrow"
format.relativeTime(new Date(now + 604800000))   // "in 1 week"

Real-World Examples

E-commerce Price Display

function PriceTag({ price, originalPrice, currency = 'USD' }) {
  const format = useFormatter()

  const discount = ((originalPrice - price) / originalPrice) * 100

  return (
    <div>
      <span className="text-2xl font-bold">
        {format.number(price, { style: 'currency', currency })}
      </span>
      {originalPrice > price && (
        <>
          <span className="line-through text-gray-500">
            {format.number(originalPrice, { style: 'currency', currency })}
          </span>
          <span className="text-green-600">
            {format.number(discount / 100, { style: 'percent' })} off
          </span>
        </>
      )}
    </div>
  )
}

Activity Feed

function ActivityItem({ action, users, timestamp }) {
  const format = useFormatter()

  return (
    <div>
      <span>{format.list(users, { type: 'conjunction' })}</span>
      <span> {action}</span>
      <time className="text-gray-500">
        {format.relativeTime(timestamp)}
      </time>
    </div>
  )
}

Statistics Dashboard

function StatCard({ label, value, type }) {
  const format = useFormatter()

  const formattedValue = () => {
    switch (type) {
      case 'currency':
        return format.number(value, { style: 'currency', currency: 'USD' })
      case 'percent':
        return format.number(value / 100, { style: 'percent' })
      case 'compact':
        return format.number(value, { notation: 'compact' })
      default:
        return format.number(value)
    }
  }

  return (
    <div className="p-4 bg-white rounded-lg shadow">
      <p className="text-sm text-gray-500">{label}</p>
      <p className="text-2xl font-bold">{formattedValue()}</p>
    </div>
  )
}
  • Translations - Translation strings with inline formatting
  • Provider - Configure timezone for formatting

On this page