{
  "version": 3,
  "sources": ["../src/main.ts"],
  "sourcesContent": ["import { createLogger } from '@alwatr/logger';\nimport { packageTracer } from '@alwatr/package-tracer';\nimport { UnicodeDigits, type UnicodeLangKeys } from '@alwatr/unicode-digits';\n\n__dev_mode__: packageTracer.add(__package_name__, __package_version__);\n\n/**\n * Represents a locale code in the format \"language-COUNTRY\".\n * The language part must be in lowercase, and the country part must be in uppercase.\n *\n * @example \"en-US\"\n * @example \"fr-FR\"\n * @example \"de-DE\"\n */\nexport type LocaleCode = `${Lowercase<string>}-${Uppercase<string>}`;\n\n/**\n * Represents a locale configuration with language code and language identifier.\n */\nexport interface Locale {\n  /**\n   * fa-IR, en-US, ...\n   */\n  code: LocaleCode;\n\n  /**\n   * The ISO 639-1 language code (e.g., 'fa', 'en')\n   */\n  language: UnicodeLangKeys;\n}\n\n/**\n * Provides localization and internationalization functionality.\n *\n * @remarks\n * This class handles number formatting, text translation, date formatting,\n * and relative time calculations based on the specified locale.\n */\nexport class Localizer {\n  /**\n   * Number formatter instance for formatting numbers according to the locale.\n   *\n   * @internal\n   */\n  protected numberFormatter_;\n\n  /**\n   * UnicodeDigits instance for converting numbers to locale-specific digits.\n   *\n   * @internal\n   */\n  protected unicodeDigits_;\n\n  protected logger_ = createLogger(__package_name__);\n\n  /**\n   * Time units used for relative time calculations.\n   * @internal\n   */\n  static timeUnits_ = [\n    { label: 'year', seconds: 31536000 },\n    { label: 'month', seconds: 2592000 },\n    { label: 'week', seconds: 604800 },\n    { label: 'day', seconds: 86400 },\n    { label: 'hour', seconds: 3600 },\n    { label: 'minute', seconds: 60 },\n    { label: 'second', seconds: 1 },\n  ] as const;\n\n  /**\n   * Creates a new instance of the Localizer class.\n   *\n   * @param options__ - Configuration options for localization\n   */\n  constructor(private options__: { locale: Locale; resource: DictionaryReq | null }) {\n    this.numberFormatter_ = new Intl.NumberFormat(this.options__.locale.code);\n    this.unicodeDigits_ = new UnicodeDigits(this.options__.locale.language);\n  }\n\n  /**\n   * Retrieves a localized message by key from the resource dictionary.\n   *\n   * @param key - The key to lookup in the resource dictionary\n   * @returns The localized message string\n   *\n   * @remarks\n   * - Returns \"\\{key\\}\" if the key is not found in the dictionary\n   * - Returns an empty string if the key is null or undefined\n   *\n   * @example\n   * ```typescript\n   * const localizer = new Localizer({...});\n   * console.log(localizer.message('hello_world')); // \"Hello world!\"\n   * console.log(localizer.message('missing_key')); // \"{missing_key}\"\n   * ```\n   */\n  message(key: keyof NonNullable<typeof this.options__.resource>): string {\n    this.logger_.logMethodArgs?.('message', key);\n    if (!key) return '';\n\n    const msg = this.options__.resource?.[key];\n    if (msg === undefined) {\n      this.logger_.accident('message', 'l10n_key_not_found', 'Key not defined in the localization resource', {\n        key,\n        locale: this.options__.locale,\n      });\n      return `{${key}}`;\n    }\n    // else\n    return msg;\n  }\n\n  /**\n   * Formats a number according to the current locale settings.\n   *\n   * @param number - The number to format\n   * @param decimal - Number of decimal places (default: 2)\n   * @returns Formatted number string using locale-specific formatting\n   *\n   * @example\n   * ```typescript\n   * const localizer = new Localizer({...});\n   * console.log(localizer.number(1234.567)); // \"1,234.57\"\n   * console.log(localizer.number(1234.567, 1)); // \"1,234.6\"\n   * ```\n   */\n  number(number?: number | null, decimal = 2): string {\n    if (number == null) return '';\n    decimal = Math.pow(10, decimal);\n    number = Math.round(number * decimal) / decimal;\n    return this.numberFormatter_.format(number);\n  }\n\n  /**\n   * Replaces all numeric digits in a string with their locale-specific Unicode equivalents.\n   *\n   * @param str - The input string containing numbers to replace\n   * @returns String with numbers converted to locale-specific digits\n   *\n   * @example\n   * ```typescript\n   * const localizer = new Localizer({locale: {code: 'fa-IR', language: 'fa'}, ...});\n   * console.log(localizer.replaceNumber('123')); // '۱۲۳'\n   * ```\n   */\n  replaceNumber(str: string): string {\n    this.logger_.logMethodArgs?.('replaceNumber', str);\n    return this.unicodeDigits_.translate(str);\n  }\n\n  /**\n   * Formats a date according to the current locale settings.\n   *\n   * @param date - Date to format (as Date object or timestamp)\n   * @param options - Intl.DateTimeFormatOptions for customizing the output\n   * @returns Localized date string\n   *\n   * @example\n   * ```typescript\n   * const localizer = new Localizer({...});\n   * console.log(localizer.time(new Date())); // \"4/21/2025\"\n   * ```\n   */\n  time(date: number | Date, options?: Intl.DateTimeFormatOptions): string {\n    this.logger_.logMethodArgs?.('time', { date, options });\n    if (typeof date === 'number') date = new Date(date);\n    return date.toLocaleDateString(this.options__.locale.code, options);\n  }\n\n  /**\n   * Creates a relative time string comparing two dates.\n   *\n   * @param date - The date to compare (as Date object or timestamp)\n   * @param from - Reference date for comparison (defaults to current time)\n   * @param options - Formatting options for relative time\n   * @returns Localized relative time string\n   *\n   * @example\n   * ```typescript\n   * const localizer = new Localizer({...});\n   * const date = new Date(Date.now() - 3600000); // 1 hour ago\n   * console.log(localizer.relativeTime(date)); // \"1 hour ago\"\n   * ```\n   */\n  relativeTime(\n    date: number | Date,\n    from: number | Date = Date.now(),\n    options: Intl.RelativeTimeFormatOptions = { numeric: 'auto', style: 'narrow' },\n  ): string {\n    this.logger_.logMethodArgs?.('relativeTime', { date, from, options });\n\n    const rtf = new Intl.RelativeTimeFormat(this.options__.locale.code, options);\n\n    if (typeof date !== 'number') date = date.getTime();\n    if (typeof from !== 'number') from = from.getTime();\n    const diffSec = (from - date) / 1000;\n\n    // Find the appropriate unit for the time difference\n    for (const unit of Localizer.timeUnits_) {\n      const interval = Math.floor(Math.abs(diffSec / unit.seconds));\n      if (interval >= 1) {\n        return rtf.format(diffSec > 0 ? interval : -interval, unit.label);\n      }\n    }\n\n    return rtf.format(0, 'second');\n  }\n}\n"],
  "mappings": "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",
  "names": []
}
