@pyyupsk/fdu

Internationalization

Comprehensive guide to internationalization in @pyyupsk/fdu. Learn how to use built-in locales including English, Spanish, French, German, Japanese, Thai (Buddhist Era), Arabic, and more. Format dates in multiple languages, create custom locale configurations with alternative calendar systems, and implement locale-aware date formatting for global applications.

@pyyupsk/fdu provides built-in support for multiple locales, allowing you to format dates in different languages and cultural conventions.

Quick Start

import { fdu, registerLocale, locale } from '@pyyupsk/fdu';
import { es } from '@pyyupsk/fdu/locale/es';
import { fr } from '@pyyupsk/fdu/locale/fr';

// Register locales
registerLocale('es', es);
registerLocale('fr', fr);

// Set global locale
locale('es');

const date = fdu('2024-01-15');
date.format('dddd, D [de] MMMM [de] YYYY');
// 'lunes, 15 de enero de 2024'

// Or use locale per instance
date.locale('fr').format('dddd D MMMM YYYY');
// 'lundi 15 janvier 2024'

Available Locales

@pyyupsk/fdu includes multiple built-in locales:

Locale CodeLanguageImport Path
enEnglish (default)@pyyupsk/fdu/locale/en
esSpanish@pyyupsk/fdu/locale/es
frFrench@pyyupsk/fdu/locale/fr
deGerman@pyyupsk/fdu/locale/de
jaJapanese@pyyupsk/fdu/locale/ja
zh-cnChinese (Simplified)@pyyupsk/fdu/locale/zh-cn

For a complete list of all available locales, see the locales directory on GitHub.


Registering Locales

Before using a locale, you must register it with registerLocale():

import { registerLocale } from '@pyyupsk/fdu';
import { es } from '@pyyupsk/fdu/locale/es';
import { fr } from '@pyyupsk/fdu/locale/fr';
import { de } from '@pyyupsk/fdu/locale/de';

// Register individual locales
registerLocale('es', es);
registerLocale('fr', fr);
registerLocale('de', de);

The English locale (en) is automatically registered and set as the default global locale.


Using Locales

There are two ways to use locales:

1. Global Locale

Set a global locale that applies to all new date instances:

import { locale } from '@pyyupsk/fdu';

// Get current global locale
locale();  // 'en'

// Set global locale
locale('es');  // 'es'

// All new instances use Spanish
const date = fdu('2024-01-15');
date.format('MMMM');  // 'enero'

2. Instance Locale

Set a locale for a specific instance (immutable - returns a new instance):

import { fdu } from '@pyyupsk/fdu';

const date = fdu('2024-01-15');

// English (default)
date.format('MMMM');  // 'January'

// Spanish
date.locale('es').format('MMMM');  // 'enero'

// French
date.locale('fr').format('MMMM');  // 'janvier'

// Original instance unchanged
date.format('MMMM');  // 'January'

Locale-Aware Format Tokens

The following format tokens change their output based on the current locale:

Month Names

import { fdu } from '@pyyupsk/fdu';

const date = fdu('2024-01-15');

// Full month name (MMMM)
date.format('MMMM');                    // 'January'
date.locale('es').format('MMMM');       // 'enero'
date.locale('fr').format('MMMM');       // 'janvier'
date.locale('de').format('MMMM');       // 'Januar'
date.locale('ja').format('MMMM');       // '1月'
date.locale('zh-cn').format('MMMM');    // '一月'

// Abbreviated month name (MMM)
date.format('MMM');                     // 'Jan'
date.locale('es').format('MMM');        // 'ene'
date.locale('fr').format('MMM');        // 'janv'

Weekday Names

import { fdu } from '@pyyupsk/fdu';

const date = fdu('2024-01-15'); // Monday

// Full weekday (dddd)
date.format('dddd');                    // 'Monday'
date.locale('es').format('dddd');       // 'lunes'
date.locale('fr').format('dddd');       // 'lundi'
date.locale('de').format('dddd');       // 'Montag'
date.locale('ja').format('dddd');       // '月曜日'
date.locale('zh-cn').format('dddd');    // '星期一'

// Short weekday (ddd)
date.format('ddd');                     // 'Mon'
date.locale('es').format('ddd');        // 'lun'
date.locale('fr').format('ddd');        // 'lun'

// Minimal weekday (dd)
date.format('dd');                      // 'Mo'
date.locale('es').format('dd');         // 'lu'
date.locale('fr').format('dd');         // 'lu'

Ordinal Numbers

import { fdu } from '@pyyupsk/fdu';

const date = fdu('2024-01-15');

date.format('Do');                      // '15th'
date.locale('es').format('Do');         // '15º'
date.locale('fr').format('Do');         // '15e'

AM/PM Indicator

import { fdu } from '@pyyupsk/fdu';

const morning = fdu('2024-01-15T09:30:00');
const afternoon = fdu('2024-01-15T14:30:00');

// English
morning.format('A');    // 'AM'
afternoon.format('A');  // 'PM'

// Some locales may customize this
// (depends on locale configuration)

Locale Examples

Here are some complete examples for different locales:

Spanish (es)

import { fdu, registerLocale } from '@pyyupsk/fdu';
import { es } from '@pyyupsk/fdu/locale/es';

registerLocale('es', es);

const date = fdu('2024-01-15T14:30:00').locale('es');

date.format('dddd, D [de] MMMM [de] YYYY');
// 'lunes, 15 de enero de 2024'

date.format('DD/MM/YYYY [a las] HH:mm');
// '15/01/2024 a las 14:30'

French (fr)

import { fdu, registerLocale } from '@pyyupsk/fdu';
import { fr } from '@pyyupsk/fdu/locale/fr';

registerLocale('fr', fr);

const date = fdu('2024-01-15T14:30:00').locale('fr');

date.format('dddd D MMMM YYYY');
// 'lundi 15 janvier 2024'

date.format('[Le] DD/MM/YYYY [à] HH:mm');
// 'Le 15/01/2024 à 14:30'

German (de)

import { fdu, registerLocale } from '@pyyupsk/fdu';
import { de } from '@pyyupsk/fdu/locale/de';

registerLocale('de', de);

const date = fdu('2024-01-15T14:30:00').locale('de');

date.format('dddd, D. MMMM YYYY');
// 'Montag, 15. Januar 2024'

date.format('DD.MM.YYYY [um] HH:mm [Uhr]');
// '15.01.2024 um 14:30 Uhr'

Japanese (ja)

import { fdu, registerLocale } from '@pyyupsk/fdu';
import { ja } from '@pyyupsk/fdu/locale/ja';

registerLocale('ja', ja);

const date = fdu('2024-01-15T14:30:00').locale('ja');

date.format('YYYY年M月D日 dddd');
// '2024年1月15日 月曜日'

date.format('YYYY年M月D日 HH:mm');
// '2024年1月15日 14:30'

Chinese Simplified (zh-cn)

import { fdu, registerLocale } from '@pyyupsk/fdu';
import { zhCn } from '@pyyupsk/fdu/locale/zh-cn';

registerLocale('zh-cn', zhCn);

const date = fdu('2024-01-15T14:30:00').locale('zh-cn');

date.format('YYYY年M月D日 dddd');
// '2024年1月15日 星期一'

date.format('M月D日 HH:mm');
// '1月15日 14:30'

Thai (th) - Buddhist Era

import { fdu, registerLocale } from '@pyyupsk/fdu';
import { th } from '@pyyupsk/fdu/locale/th';

registerLocale('th', th);

const date = fdu('2025-01-15T14:30:00').locale('th');

// Buddhist Era calendar (2025 + 543 = 2568)
date.format('dddd, D MMMM YYYY');
// 'วันพุธ, 15 มกราคม 2568'

date.format('D MMMM YYYY เวลา H:mm');
// '15 มกราคม 2568 เวลา 14:30'

Creating Custom Locales

You can create your own custom locale configurations:

import type { LocaleConfig } from '@pyyupsk/fdu';
import { registerLocale } from '@pyyupsk/fdu';

const customLocale: LocaleConfig = {
  name: 'custom',

  // Full month names (required)
  months: [
    'January', 'February', 'March', 'April', 'May', 'June',
    'July', 'August', 'September', 'October', 'November', 'December'
  ],

  // Abbreviated month names (optional)
  monthsShort: [
    'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
  ],

  // Full weekday names (required, Sunday-Saturday)
  weekdays: [
    'Sunday', 'Monday', 'Tuesday', 'Wednesday',
    'Thursday', 'Friday', 'Saturday'
  ],

  // Abbreviated weekday names (optional)
  weekdaysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],

  // Minimal weekday names (optional)
  weekdaysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],

  // First day of week (optional, 0=Sunday, 1=Monday, etc.)
  weekStart: 0,

  // Common format patterns (optional)
  formats: {
    LT: 'h:mm A',                        // Time
    LTS: 'h:mm:ss A',                    // Time with seconds
    L: 'MM/DD/YYYY',                     // Short date
    LL: 'MMMM D, YYYY',                  // Long date
    LLL: 'MMMM D, YYYY h:mm A',          // Long date with time
    LLLL: 'dddd, MMMM D, YYYY h:mm A'    // Full date with weekday
  },

  // Ordinal suffix function (optional)
  ordinal: (n) => {
    const s = ['th', 'st', 'nd', 'rd'];
    const v = n % 100;
    return n + (s[(v - 20) % 10] || s[v] || s[0]);
  },

  // AM/PM formatter (optional)
  meridiem: (hour, minute, isLower) => {
    if (hour < 12) {
      return isLower ? 'am' : 'AM';
    }
    return isLower ? 'pm' : 'PM';
  }
};

registerLocale('custom', customLocale);

LocaleConfig Type

type LocaleConfig = {
  name: string;
  yearOffset?: number; // For alternative calendar systems
  months: readonly [string, string, ...]; // 12 items
  monthsShort?: readonly [string, string, ...]; // 12 items
  weekdays: readonly [string, string, ...]; // 7 items (Sun-Sat)
  weekdaysShort?: readonly [string, string, ...]; // 7 items
  weekdaysMin?: readonly [string, string, ...]; // 7 items
  weekStart?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
  formats?: {
    LT?: string;
    LTS?: string;
    L?: string;
    LL?: string;
    LLL?: string;
    LLLL?: string;
  };
  ordinal?: (n: number, period?: string) => string;
  meridiem?: (hour: number, minute: number, isLower?: boolean) => string;
};

Alternative Calendar Systems

Some locales use alternative calendar systems with different year numbering. You can configure this using the yearOffset property.

Thai Buddhist Era

The Thai locale uses the Buddhist Era calendar, which is 543 years ahead of the Gregorian calendar:

import { fdu, registerLocale } from '@pyyupsk/fdu';
import { th } from '@pyyupsk/fdu/locale/th';

registerLocale('th', th);

const date = fdu('2025-01-15').locale('th');

// Buddhist Era: 2025 + 543 = 2568
date.format('YYYY-MM-DD');
// '2568-01-15'

date.format('D MMMM YYYY');
// '15 มกราคม 2568'

date.format('dddd, D MMMM YYYY');
// 'วันพุธ, 15 มกราคม 2568'

Creating Custom Calendar Systems

You can create your own locale with a custom year offset:

import type { LocaleConfig } from '@pyyupsk/fdu';
import { registerLocale } from '@pyyupsk/fdu';

const customCalendar: LocaleConfig = {
  name: 'custom',
  yearOffset: 100, // Add 100 years
  months: [...],
  weekdays: [...],
  // ... other config
};

registerLocale('custom', customCalendar);

const date = fdu('2025-01-15').locale('custom');
date.format('YYYY'); // '2125'

The yearOffset property only affects the display of years in YYYY and YY format tokens. It does not affect the underlying date value or any date calculations.


Week Start Configuration

Different cultures have different conventions for which day starts the week:

// English (week starts on Sunday)
en.weekStart = 0;  // Sunday

// French (week starts on Monday)
fr.weekStart = 1;  // Monday

// Custom locale with Saturday as first day
const customLocale: LocaleConfig = {
  // ... other config
  weekStart: 6  // Saturday
};

The weekStart property is primarily informational. It doesn't affect date calculations but can be useful for calendar displays and other UI components.


Best Practices

Import Only What You Need

To keep your bundle size small, only import the locales you actually use:

// ✅ Good - only import needed locales
import { es } from '@pyyupsk/fdu/locale/es';
import { fr } from '@pyyupsk/fdu/locale/fr';

// ❌ Avoid - don't import all locales if you don't need them
import * as allLocales from '@pyyupsk/fdu/locale';

Register Locales Once

Register locales at application startup, not on every use:

// ✅ Good - register once at startup
// app-initialization.ts
import { registerLocale } from '@pyyupsk/fdu';
import { es } from '@pyyupsk/fdu/locale/es';

registerLocale('es', es);

// ❌ Avoid - don't register repeatedly
function formatDate() {
  registerLocale('es', es); // Don't do this on every call
  return fdu().locale('es').format('YYYY-MM-DD');
}

Handle Missing Locales

Always handle cases where a locale might not be registered:

import { locale, registerLocale } from '@pyyupsk/fdu';
import { es } from '@pyyupsk/fdu/locale/es';

// Ensure locale is registered before using
function setAppLocale(localeName: string) {
  // Register if needed
  if (localeName === 'es') {
    registerLocale('es', es);
  }

  locale(localeName);
}

If you try to use an unregistered locale, @pyyupsk/fdu will log a warning and fall back to English ('en').


See Also