UNPKG

@nexim/localizer

Version:

Lightweight i18n utilities to handle translations, number formatting, date/time localization using native browser APIs.

146 lines 5.17 kB
import { createLogger } from './logger.js'; import { convertDigits } from './unicode-digits.js'; const logger = createLogger('@nexim/localizer'); /** * Provides localization and internationalization functionality. * * @remarks * This class handles number formatting, text translation, date formatting, * and relative time calculations based on the specified locale. */ export class Localizer { /** * Time units used for relative time calculations. * @internal */ constructor(options__) { this.options__ = options__; this.numberFormatter_ = new Intl.NumberFormat(this.options__.locale.code); } /** * Retrieves a localized message by key from the resource dictionary. * * @param key - The key to lookup in the resource dictionary * @returns The localized message string * * @remarks * - Returns "\{key\}" if the key is not found in the dictionary * - Returns an empty string if the key is null or undefined * * @example * ```typescript * const localizer = new Localizer({...}); * console.log(localizer.message('hello_world')); // "Hello world!" * console.log(localizer.message('missing_key')); // "{missing_key}" * ``` */ message(key) { if (!key) return ''; const msg = this.options__.resource?.[key]; if (msg === undefined) { logger.error('message', `key_not_found: ${key}`); return `{${key}}`; } return msg; } /** * Formats a number according to the current locale settings. * * @param number - The number to format * @param decimal - Number of decimal places (default: 2) * @returns Formatted number string using locale-specific formatting * * @example * ```typescript * const localizer = new Localizer({...}); * console.log(localizer.number(1234.567)); // "1,234.57" * console.log(localizer.number(1234.567, 1)); // "1,234.6" * ``` */ number(number, decimal = 2) { if (number == null) return ''; decimal = Math.pow(10, decimal); number = Math.round(number * decimal) / decimal; return this.numberFormatter_.format(number); } /** * Replaces all numeric digits in a string with their locale-specific Unicode equivalents. * * @param str - The input string containing numbers to replace * @returns String with numbers converted to locale-specific digits * * @example * ```typescript * const localizer = new Localizer({locale: {code: 'fa-IR', language: 'fa'}, ...}); * console.log(localizer.replaceNumber('123')); // '۱۲۳' * ``` */ replaceNumber(str) { return convertDigits(str, this.options__.locale.language); } /** * Formats a date according to the current locale settings. * * @param date - Date to format (as Date object or timestamp) * @param options - Intl.DateTimeFormatOptions for customizing the output * @returns Localized date string * * @example * ```typescript * const localizer = new Localizer({...}); * console.log(localizer.time(new Date())); // "4/21/2025" * ``` */ time(date, options) { if (typeof date === 'number') date = new Date(date); return date.toLocaleDateString(this.options__.locale.code, options); } /** * Creates a relative time string comparing two dates. * * @param date - The date to compare (as Date object or timestamp) * @param from - Reference date for comparison (defaults to current time) * @param options - Formatting options for relative time * @returns Localized relative time string * * @example * ```typescript * const localizer = new Localizer({...}); * const date = new Date(Date.now() - 3600000); // 1 hour ago * console.log(localizer.relativeTime(date)); // "1 hour ago" * ``` */ relativeTime(date, from = Date.now(), options = { numeric: 'auto', style: 'narrow' }) { const rtf = new Intl.RelativeTimeFormat(this.options__.locale.code, options); if (typeof date !== 'number') date = date.getTime(); if (typeof from !== 'number') from = from.getTime(); const diffSec = (from - date) / 1000; // Find the appropriate unit for the time difference for (const unit of Localizer.timeUnits_) { const interval = Math.floor(Math.abs(diffSec / unit.seconds)); if (interval >= 1) { return rtf.format(diffSec > 0 ? interval : -interval, unit.label); } } return rtf.format(0, 'second'); } } /** * Time units used for relative time calculations. * @internal */ Localizer.timeUnits_ = [ { label: 'year', seconds: 31536000 }, { label: 'month', seconds: 2592000 }, { label: 'week', seconds: 604800 }, { label: 'day', seconds: 86400 }, { label: 'hour', seconds: 3600 }, { label: 'minute', seconds: 60 }, { label: 'second', seconds: 1 }, ]; //# sourceMappingURL=main.js.map