or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

arithmetic.mdcomponents.mdconstants.mdformatting.mdfp.mdi18n.mdindex.mdparsing.mdperiods.mdvalidation.md
tile.json

i18n.mddocs/

Internationalization

The date-fns internationalization system provides comprehensive support for 97+ languages and regions with customizable date formatting, relative time display, and cultural date conventions. All locale functionality is modular and tree-shakeable.

Locale System Overview

Locale Interface

interface Locale {
  code: string;
  formatDistance?: FormatDistanceFn;
  formatLong?: FormatLongOptions;
  formatRelative?: FormatRelativeFn;
  localize?: LocalizeOptions;
  match?: MatchOptions;
  options?: LocaleOptions;
}

The locale object contains all language-specific formatting rules and translations needed for date operations in different languages and regions.

Supported Locales

Major Language Families

English Variants

  • enUS - English (United States) - Default
  • enGB - English (United Kingdom)
  • enCA - English (Canada)
  • enAU - English (Australia)
  • enNZ - English (New Zealand)
  • enIN - English (India)
  • enIE - English (Ireland)
  • enZA - English (South Africa)

European Languages

  • de - German (Germany)
  • deAT - German (Austria)
  • fr - French (France)
  • frCA - French (Canada)
  • frCH - French (Switzerland)
  • es - Spanish (Spain)
  • it - Italian (Italy)
  • itCH - Italian (Switzerland)
  • pt - Portuguese (Portugal)
  • ptBR - Portuguese (Brazil)
  • nl - Dutch (Netherlands)
  • nlBE - Dutch (Belgium)

Nordic Languages

  • da - Danish
  • sv - Swedish
  • nb - Norwegian Bokmål
  • nn - Norwegian Nynorsk
  • fi - Finnish
  • is - Icelandic

Slavic Languages

  • ru - Russian
  • pl - Polish
  • cs - Czech
  • sk - Slovak
  • sl - Slovenian
  • hr - Croatian
  • sr - Serbian (Cyrillic)
  • srLatn - Serbian (Latin)
  • bg - Bulgarian
  • mk - Macedonian
  • be - Belarusian
  • beTarask - Belarusian (Taraskievica)
  • uk - Ukrainian

Asian Languages

  • zhCN - Chinese (Simplified, China)
  • zhHK - Chinese (Traditional, Hong Kong)
  • zhTW - Chinese (Traditional, Taiwan)
  • ja - Japanese
  • jaHira - Japanese (Hiragana)
  • ko - Korean
  • th - Thai
  • vi - Vietnamese
  • hi - Hindi
  • bn - Bengali
  • gu - Gujarati
  • kn - Kannada
  • ta - Tamil
  • te - Telugu

Middle Eastern & African

  • ar - Arabic
  • arDZ - Arabic (Algeria)
  • arEG - Arabic (Egypt)
  • arMA - Arabic (Morocco)
  • arSA - Arabic (Saudi Arabia)
  • arTN - Arabic (Tunisia)
  • he - Hebrew
  • faIR - Persian (Iran)
  • tr - Turkish
  • af - Afrikaans

Complete Locale List

// Import specific locales
import { enUS, de, fr, ja, zhCN, ar } from "date-fns/locale";

// Available locales (97 total)
const locales = [
  'af', 'ar', 'arDZ', 'arEG', 'arMA', 'arSA', 'arTN',
  'az', 'be', 'beTarask', 'bg', 'bn', 'bs', 'ca', 'ckb',
  'cs', 'cy', 'da', 'de', 'deAT', 'el', 'enAU', 'enCA',
  'enGB', 'enIE', 'enIN', 'enNZ', 'enUS', 'enZA', 'eo',
  'es', 'et', 'eu', 'faIR', 'fi', 'fr', 'frCA', 'frCH',
  'fy', 'gd', 'gl', 'gu', 'he', 'hi', 'hr', 'ht', 'hu',
  'hy', 'id', 'is', 'it', 'itCH', 'ja', 'jaHira', 'ka',
  'kk', 'km', 'kn', 'ko', 'lb', 'lt', 'lv', 'mk', 'mn',
  'ms', 'mt', 'nb', 'nl', 'nlBE', 'nn', 'oc', 'pl', 'pt',
  'ptBR', 'ro', 'ru', 'se', 'sk', 'sl', 'sq', 'sr', 'srLatn',
  'sv', 'ta', 'te', 'th', 'tr', 'ug', 'uk', 'uz', 'uzCyrl',
  'vi', 'zhCN', 'zhHK', 'zhTW'
];

Using Locales

Basic Locale Usage

import { format, formatDistance, formatRelative } from "date-fns";
import { de, fr, ja, zhCN } from "date-fns/locale";

const date = new Date(2014, 1, 11);

// German
format(date, "EEEE, do MMMM yyyy", { locale: de });
//=> 'Dienstag, 11. Februar 2014'

// French  
format(date, "EEEE, do MMMM yyyy", { locale: fr });
//=> 'mardi, 11e février 2014'

// Japanese
format(date, "EEEE, do MMMM yyyy", { locale: ja });
//=> '火曜日, 11日 2月 2014'

// Chinese (Simplified)
format(date, "EEEE, do MMMM yyyy", { locale: zhCN });
//=> '星期二, 11日 二月 2014'

Distance Formatting with Locales

import { formatDistance, formatDistanceToNow } from "date-fns";
import { de, es, ru, ar } from "date-fns/locale";

const date1 = new Date(2014, 6, 2);
const date2 = new Date(2015, 0, 1);

// German
formatDistance(date2, date1, { locale: de });
//=> 'etwa 6 Monate'

// Spanish
formatDistance(date2, date1, { locale: es });
//=> 'alrededor de 6 meses'

// Russian
formatDistance(date2, date1, { locale: ru });
//=> 'около 6 месяцев'

// Arabic
formatDistance(date2, date1, { locale: ar });
//=> 'حوالي 6 أشهر'

Relative Formatting with Locales

import { formatRelative } from "date-fns";
import { de, fr, ja } from "date-fns/locale";

const baseDate = new Date(2000, 0, 1, 0, 0, 0); // Jan 1, 2000
const date = new Date(1999, 11, 27); // Dec 27, 1999

// German
formatRelative(date, baseDate, { locale: de });
//=> 'letzten Montag um 00:00'

// French
formatRelative(date, baseDate, { locale: fr });
//=> 'lundi dernier à 00:00'

// Japanese  
formatRelative(date, baseDate, { locale: ja });
//=> '先週の月曜日 0:00'

Locale Configuration Options

Week Configuration

import { format, startOfWeek } from "date-fns";
import { de, ar, enUS } from "date-fns/locale";

const date = new Date(2014, 1, 11); // Tuesday

// Different week start days by locale
startOfWeek(date, { locale: enUS }); // Sunday start
//=> Sun Feb 09 2014

startOfWeek(date, { locale: de }); // Monday start  
//=> Mon Feb 10 2014

// Manual override
startOfWeek(date, { locale: enUS, weekStartsOn: 1 }); // Force Monday start
//=> Mon Feb 10 2014

First Week Configuration

import { getWeek } from "date-fns";
import { de, enUS } from "date-fns/locale";

const date = new Date(2014, 0, 1); // Jan 1, 2014

// Different first week rules
getWeek(date, { locale: enUS }); 
//=> 1 (US: week containing Jan 1 is week 1)

getWeek(date, { locale: de });
//=> 1 (German: week with 4+ days in new year is week 1)

Locale-Specific Patterns

Date Patterns by Locale

import { format } from "date-fns";
import { enUS, de, ja, ar } from "date-fns/locale";

const date = new Date(2014, 1, 11);

// US format (M/d/yyyy)
format(date, "P", { locale: enUS });
//=> '2/11/2014'

// German format (dd.MM.yyyy)
format(date, "P", { locale: de });
//=> '11.02.2014'

// Japanese format (yyyy/MM/dd)  
format(date, "P", { locale: ja });
//=> '2014/02/11'

// Arabic format (d‏/M‏/yyyy)
format(date, "P", { locale: ar });
//=> '11‏/2‏/2014'

Time Patterns by Locale

import { format } from "date-fns";
import { enUS, de, ja } from "date-fns/locale";

const date = new Date(2014, 1, 11, 14, 30);

// US format (2:30 PM)
format(date, "p", { locale: enUS });
//=> '2:30 PM'

// German format (14:30)
format(date, "p", { locale: de });
//=> '14:30'

// Japanese format (14:30)
format(date, "p", { locale: ja });
//=> '14:30'

Long Format Patterns

import { format } from "date-fns";
import { enUS, de, fr, ja } from "date-fns/locale";

const date = new Date(2014, 1, 11, 14, 30, 45);

// Full date and time formats
format(date, "PPPPpppp", { locale: enUS });
//=> 'Tuesday, February 11th, 2014 at 2:30:45 PM GMT+2'

format(date, "PPPPpppp", { locale: de });
//=> 'Dienstag, 11. Februar 2014 um 14:30:45 GMT+2'

format(date, "PPPPpppp", { locale: fr });
//=> 'mardi 11 février 2014 à 14:30:45 GMT+2'

format(date, "PPPPpppp", { locale: ja });
//=> '2014年2月11日火曜日 14:30:45 GMT+2'

Creating Custom Locales

Locale Structure

interface Locale {
  code: string;
  formatDistance: FormatDistanceFn;
  formatLong: FormatLongOptions;
  formatRelative: FormatRelativeFn;
  localize: LocalizeOptions;
  match: MatchOptions;
  options?: LocaleOptions;
}

Custom Locale Example

import { Locale } from "date-fns";

const customLocale: Locale = {
  code: 'custom',
  
  formatDistance: (token, count, options) => {
    // Custom distance formatting logic
    const formatDistanceLocale = {
      lessThanXSeconds: 'less than {{count}} second{{s}}',
      xSeconds: '{{count}} second{{s}}',
      halfAMinute: 'half a minute',
      lessThanXMinutes: 'less than {{count}} minute{{s}}',
      xMinutes: '{{count}} minute{{s}}',
      aboutXHours: 'about {{count}} hour{{s}}',
      xHours: '{{count}} hour{{s}}',
      xDays: '{{count}} day{{s}}',
      aboutXWeeks: 'about {{count}} week{{s}}',
      xWeeks: '{{count}} week{{s}}',
      aboutXMonths: 'about {{count}} month{{s}}',
      xMonths: '{{count}} month{{s}}',
      aboutXYears: 'about {{count}} year{{s}}',
      xYears: '{{count}} year{{s}}',
      overXYears: 'over {{count}} year{{s}}',
      almostXYears: 'almost {{count}} year{{s}}'
    };

    const result = formatDistanceLocale[token].replace(
      '{{count}}', 
      count.toString()
    );
    
    return result.replace('{{s}}', count === 1 ? '' : 's');
  },

  formatLong: {
    time: 'HH:mm:ss',
    date: 'dd/MM/yyyy',
    dateTime: '{{date}} {{time}}',
    longDate: 'MMMM d, yyyy',
    fullDate: 'EEEE, MMMM do, yyyy',
    shortTime: 'HH:mm',
    longTime: 'HH:mm:ss',
    fullTime: 'HH:mm:ss'
  },

  formatRelative: (token, date, baseDate, options) => {
    // Custom relative formatting
    const formatRelativeLocale = {
      lastWeek: "'last' eeee 'at' p",
      yesterday: "'yesterday at' p",
      today: "'today at' p", 
      tomorrow: "'tomorrow at' p",
      nextWeek: "eeee 'at' p",
      other: 'P'
    };
    
    return formatRelativeLocale[token];
  },

  localize: {
    // Month names, day names, etc.
    month: (month) => ['Jan', 'Feb', 'Mar', /*...*/][month],
    day: (day) => ['Sun', 'Mon', 'Tue', /*...*/][day],
    // Additional localization functions...
  },

  match: {
    // Parsing patterns for custom locale
    // Match functions for parsing formatted dates
  },

  options: {
    weekStartsOn: 1, // Monday
    firstWeekContainsDate: 4
  }
};

Using Custom Locales

import { format } from "date-fns";

// Use the custom locale
format(new Date(), "PPP", { locale: customLocale });

Locale Helper Functions

Locale Detection

// Browser locale detection
function getBrowserLocale(): string {
  return navigator.language || navigator.languages[0] || 'en-US';
}

// Map browser locale to date-fns locale
function getDateFnsLocale(browserLocale: string): Locale {
  const localeMap: Record<string, () => Promise<Locale>> = {
    'de': () => import('date-fns/locale/de'),
    'de-DE': () => import('date-fns/locale/de'),
    'fr': () => import('date-fns/locale/fr'),
    'fr-FR': () => import('date-fns/locale/fr'),
    // Add more mappings...
  };
  
  const loader = localeMap[browserLocale] || 
                 localeMap[browserLocale.split('-')[0]] ||
                 (() => import('date-fns/locale/en-US'));
  
  return loader();
}

Dynamic Locale Loading

// Lazy load locales
class LocaleManager {
  private loadedLocales = new Map<string, Locale>();
  
  async getLocale(code: string): Promise<Locale> {
    if (this.loadedLocales.has(code)) {
      return this.loadedLocales.get(code)!;
    }
    
    try {
      const locale = await import(`date-fns/locale/${code}`);
      this.loadedLocales.set(code, locale.default);
      return locale.default;
    } catch {
      // Fallback to English
      const enUS = await import('date-fns/locale/en-US');
      return enUS.default;
    }
  }
}

Right-to-Left (RTL) Support

Arabic and Hebrew Examples

import { format } from "date-fns";
import { ar, he } from "date-fns/locale";

const date = new Date(2014, 1, 11);

// Arabic (RTL)
format(date, "EEEE، do MMMM yyyy", { locale: ar });
//=> 'الثلاثاء، 11 فبراير 2014'

// Hebrew (RTL)  
format(date, "EEEE, do MMMM yyyy", { locale: he });
//=> 'יום שלישי, 11 פברואר 2014'

Handling RTL in Applications

import { ar, he, enUS } from "date-fns/locale";

function isRTLLocale(locale: Locale): boolean {
  const rtlCodes = ['ar', 'he', 'fa', 'ur'];
  return rtlCodes.includes(locale.code);
}

function formatWithDirection(date: Date, pattern: string, locale: Locale): {
  text: string;
  direction: 'ltr' | 'rtl';
} {
  return {
    text: format(date, pattern, { locale }),
    direction: isRTLLocale(locale) ? 'rtl' : 'ltr'
  };
}

Option Types

LocaleOptions

interface LocaleOptions {
  weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
  firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7;
}

FormatLongOptions

interface FormatLongOptions {
  time?: string;
  date?: string;
  dateTime?: string;
  longDate?: string;
  fullDate?: string;
  shortTime?: string;
  longTime?: string;
  fullTime?: string;
}

FormatDistanceFn

type FormatDistanceFn = (
  token: string,
  count: number,
  options?: { addSuffix?: boolean; comparison?: number }
) => string;

FormatRelativeFn

type FormatRelativeFn = (
  token: 'lastWeek' | 'yesterday' | 'today' | 'tomorrow' | 'nextWeek' | 'other',
  date: Date,
  baseDate: Date,
  options?: any
) => string;