Skip to content

Locale Formatting

22.3.1. Date/Time Format

Dates and times must be formatted according to locale using the datetimeFormats configuration in vue-i18n.

typescript
const datetimeFormats = {
  ko: {
    short: { year: 'numeric', month: '2-digit', day: '2-digit' },
    long: { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' },
    full: { year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' },
  },
}
const i18n = createI18n({ datetimeFormats })
  • The $d() helper must be used for date/time display.

  • Usage examples: $d(new Date(), 'short') -> 2026. 03. 01., $d(new Date(), 'long') -> 2026년 3월 1일 일요일

  • At minimum, three formats must be defined: short, long, and full.

  • The same format names must be defined for all supported locales.

  • Date strings must not be manually assembled (YYYY-MM-DD); they must always be output through format helpers.


22.3.2. Number/Currency Format

Numbers and currencies must be formatted according to locale using the numberFormats configuration in vue-i18n.

typescript
const numberFormats = {
  ko: {
    currency: { style: 'currency', currency: 'KRW' },
    decimal: { style: 'decimal', maximumFractionDigits: 2 },
    percent: { style: 'percent', maximumFractionDigits: 1 },
  },
}
const i18n = createI18n({ numberFormats })
  • The $n() helper must be used for number display.

  • Usage examples: $n(1234567, 'currency') -> ₩1,234,567, $n(0.856, 'percent') -> 85.6%

  • Three formats must be defined as mandatory: currency, decimal, and percent.

  • The currency code (currency) must be set to the appropriate value for each locale.

  • Numbers must not be formatted directly with toLocaleString(); they must be output through the $n() helper.


22.3.3. Relative Time

Relative time expressions ("3 minutes ago", "in 2 days") must be implemented using Intl.RelativeTimeFormat.

typescript
// src/composables/useTimeAgo.ts
import { computed, type Ref } from 'vue'
import { useI18n } from 'vue-i18n'

export function useTimeAgo(date: Ref<Date>) {
  const { locale } = useI18n()
  return computed(() => {
    const diff = date.value.getTime() - Date.now()
    const abs = Math.abs(diff)
    const rtf = new Intl.RelativeTimeFormat(locale.value, { numeric: 'auto' })
    if (abs < 60_000) return rtf.format(Math.round(diff / 1000), 'second')
    if (abs < 3_600_000) return rtf.format(Math.round(diff / 60_000), 'minute')
    if (abs < 86_400_000) return rtf.format(Math.round(diff / 3_600_000), 'hour')
    return rtf.format(Math.round(diff / 86_400_000), 'day')
  })
}
  • A useTimeAgo composable must be implemented within the project for reuse of relative time expressions.
  • Strings must not be manually assembled (e.g., "3 minutes ago"); Intl.RelativeTimeFormat must be used.
  • Using the numeric: 'auto' option to generate natural expressions such as "yesterday" and "tomorrow" is recommended.

22.3.4. Intl API Usage

The browser's built-in Intl API must be used for locale-based formatting.

APIPurpose
Intl.DateTimeFormatDate/time formatting
Intl.NumberFormatNumber/currency formatting
Intl.RelativeTimeFormatRelative time expressions
Intl.CollatorString sorting
  • When sorting strings, Intl.Collator must be used to apply locale-appropriate sort order.
typescript
const collator = new Intl.Collator('ko', { sensitivity: 'base' })
const sorted = names.sort(collator.compare)
  • All modern browsers support this API, so it may be used without polyfills.
  • The Intl API must be prioritized over custom format functions.

TIENIPIA QUALIFIED STANDARD