@quantabit/i18n-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/core/I18nManager.js","../src/i18n/index.js","../src/components/I18nProvider.jsx","../src/components/LanguageSwitcher.jsx","../src/index.js"],"sourcesContent":["/**\n * @quantabit/i18n-sdk - I18nManager\n * \n * 轻量级国际化管理器\n * 特性:\n * - 多语言消息管理与切换\n * - 嵌套键路径支持 (e.g. 'nav.home')\n * - 参数插值 ({name} → 'Tom')\n * - 复数形式支持\n * - 回退语言链\n * - 语言自动检测 (浏览器偏好)\n * - 懒加载语言包\n * - 变更事件监听\n */\nexport class I18nManager {\n constructor(config = {}) {\n this.locale = config.defaultLocale || 'en';\n this._messages = config.messages || {};\n this._listeners = [];\n this._fallback = config.fallbackLocale || 'en';\n this._loading = new Set(); // 正在加载的语言包\n this._loaders = {}; // 语言包加载器\n this._dateFormats = {}; // 日期格式化配置\n this._numberFormats = {}; // 数字格式化配置\n this._debug = config.debug || false;\n\n // 自动检测浏览器语言\n if (config.autoDetect !== false && typeof navigator !== 'undefined') {\n const browserLang = this._detectBrowserLanguage();\n if (browserLang && this._messages[browserLang]) {\n this.locale = browserLang;\n }\n }\n }\n\n // ============ 基础 API ============\n\n /** 当前语言代码 */\n get currentLocale() {\n return this.locale;\n }\n\n /** 可用语言列表 */\n get availableLocales() {\n return Object.keys(this._messages);\n }\n\n /**\n * 切换语言\n * @param {string} locale - 语言代码\n * @returns {Promise<boolean>} 是否成功\n */\n async setLocale(locale) {\n // 如果语言包不存在且有加载器,尝试懒加载\n if (!this._messages[locale] && this._loaders[locale]) {\n await this.loadLocale(locale);\n }\n\n if (this._messages[locale]) {\n const oldLocale = this.locale;\n this.locale = locale;\n \n // 保存到浏览器\n if (typeof localStorage !== 'undefined') {\n try { localStorage.setItem('qbit_locale', locale); } catch {}\n }\n\n // 设置 HTML lang 属性\n if (typeof document !== 'undefined') {\n document.documentElement.lang = locale;\n // RTL 语言支持\n const rtlLocales = ['ar', 'he', 'fa', 'ur'];\n document.documentElement.dir = rtlLocales.includes(locale) ? 'rtl' : 'ltr';\n }\n\n // 通知监听器\n this._listeners.forEach(fn => fn(locale, oldLocale));\n return true;\n }\n\n if (this._debug) {\n console.warn(`[i18n] 语言 \"${locale}\" 不可用。可用语言: ${this.availableLocales.join(', ')}`);\n }\n return false;\n }\n\n /**\n * 添加语言消息\n * @param {string} locale - 语言代码\n * @param {Object} messages - 消息对象(支持嵌套)\n */\n addMessages(locale, messages) {\n this._messages[locale] = this._deepMerge(this._messages[locale] || {}, messages);\n }\n\n /**\n * 翻译 — 核心 API\n * @param {string} key - 翻译键(支持嵌套 'nav.home')\n * @param {Object} params - 插值参数\n * @returns {string} 翻译结果\n * \n * @example\n * i18n.t('greeting', { name: 'Tom' }) // \"Hello, Tom!\"\n * i18n.t('items', { count: 3 }) // \"3 items\" (复数)\n * i18n.t('nav.settings.privacy') // 嵌套键路径\n */\n t(key, params = {}) {\n // 1. 查找当前语言\n let msg = this._getNestedValue(this._messages[this.locale], key);\n\n // 2. 回退到默认语言\n if (msg === undefined || msg === null) {\n msg = this._getNestedValue(this._messages[this._fallback], key);\n }\n\n // 3. 都找不到,返回键名本身(开发友好)\n if (msg === undefined || msg === null) {\n if (this._debug) {\n console.warn(`[i18n] 缺失翻译: \"${key}\" (${this.locale})`);\n }\n return key;\n }\n\n // 4. 复数处理\n if (typeof msg === 'object' && params.count !== undefined) {\n msg = this._resolvePlural(msg, params.count);\n }\n\n // 5. 参数插值\n if (typeof msg === 'string' && params) {\n return this._interpolate(msg, params);\n }\n\n return msg;\n }\n\n /**\n * 检查翻译键是否存在\n * @param {string} key - 翻译键\n * @returns {boolean}\n */\n exists(key) {\n return this._getNestedValue(this._messages[this.locale], key) !== undefined;\n }\n\n // ============ 语言包管理 ============\n\n /**\n * 注册语言包懒加载器\n * @param {string} locale - 语言代码\n * @param {Function} loader - 异步加载函数,返回 Promise<messages>\n * \n * @example\n * i18n.registerLoader('ja', () => import('./locales/ja.json'))\n */\n registerLoader(locale, loader) {\n this._loaders[locale] = loader;\n }\n\n /**\n * 懒加载语言包\n * @param {string} locale - 语言代码\n */\n async loadLocale(locale) {\n if (this._messages[locale] || this._loading.has(locale)) return;\n\n const loader = this._loaders[locale];\n if (!loader) {\n if (this._debug) console.warn(`[i18n] 无 \"${locale}\" 加载器`);\n return;\n }\n\n this._loading.add(locale);\n try {\n const messages = await loader();\n // 兼顾 ES Module default export\n this.addMessages(locale, messages.default || messages);\n } catch (err) {\n console.error(`[i18n] 加载 \"${locale}\" 失败:`, err);\n } finally {\n this._loading.delete(locale);\n }\n }\n\n // ============ 格式化 ============\n\n /**\n * 格式化日期\n * @param {Date|number|string} date - 日期\n * @param {string} format - 格式名 ('short', 'long', 'full') 或自定义 Intl options\n */\n formatDate(date, format = 'short') {\n const d = date instanceof Date ? date : new Date(date);\n const presets = {\n short: { year: 'numeric', month: '2-digit', day: '2-digit' },\n long: { year: 'numeric', month: 'long', day: 'numeric' },\n full: { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' },\n time: { hour: '2-digit', minute: '2-digit' },\n datetime: { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' },\n };\n\n const options = typeof format === 'string' ? (presets[format] || presets.short) : format;\n return new Intl.DateTimeFormat(this.locale, options).format(d);\n }\n\n /**\n * 格式化数字\n * @param {number} num - 数字\n * @param {string|Object} format - 格式名 ('decimal', 'currency', 'percent') 或自定义\n */\n formatNumber(num, format = 'decimal') {\n const presets = {\n decimal: {},\n currency: { style: 'currency', currency: 'USD' },\n percent: { style: 'percent', minimumFractionDigits: 1 },\n compact: { notation: 'compact' },\n };\n\n const options = typeof format === 'string' ? (presets[format] || {}) : format;\n return new Intl.NumberFormat(this.locale, options).format(num);\n }\n\n /**\n * 相对时间格式化\n * @param {Date|number} date - 目标时间\n */\n formatRelative(date) {\n const d = date instanceof Date ? date : new Date(date);\n const now = Date.now();\n const diffMs = d.getTime() - now;\n const absDiff = Math.abs(diffMs);\n\n const units = [\n { unit: 'year', ms: 31536000000 },\n { unit: 'month', ms: 2592000000 },\n { unit: 'week', ms: 604800000 },\n { unit: 'day', ms: 86400000 },\n { unit: 'hour', ms: 3600000 },\n { unit: 'minute', ms: 60000 },\n { unit: 'second', ms: 1000 },\n ];\n\n for (const { unit, ms } of units) {\n if (absDiff >= ms) {\n const value = Math.round(diffMs / ms);\n try {\n return new Intl.RelativeTimeFormat(this.locale, { numeric: 'auto' }).format(value, unit);\n } catch {\n // Fallback: 简单文本\n const absVal = Math.abs(value);\n return diffMs < 0 ? `${absVal} ${unit}(s) ago` : `in ${absVal} ${unit}(s)`;\n }\n }\n }\n\n return this.locale.startsWith('zh') ? '刚刚' : 'just now';\n }\n\n // ============ 事件监听 ============\n\n /**\n * 监听语言变更\n * @param {Function} callback - (newLocale, oldLocale) => void\n * @returns {Function} 取消监听函数\n */\n onChange(callback) {\n this._listeners.push(callback);\n return () => {\n this._listeners = this._listeners.filter(f => f !== callback);\n };\n }\n\n // ============ 内部方法 ============\n\n /** 检测浏览器语言偏好 */\n _detectBrowserLanguage() {\n // 先查 localStorage\n try {\n const saved = localStorage.getItem('qbit_locale');\n if (saved) return saved;\n } catch {}\n\n // 浏览器语言\n const lang = navigator.language || navigator.userLanguage;\n return lang;\n }\n\n /** 嵌套键路径取值 (e.g. 'nav.home' → messages.nav.home) */\n _getNestedValue(obj, key) {\n if (!obj || !key) return undefined;\n\n // 先精确匹配\n if (obj[key] !== undefined) return obj[key];\n\n // 嵌套路径\n const parts = key.split('.');\n let current = obj;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined;\n }\n current = current[part];\n }\n return current;\n }\n\n /** 参数插值 {name} → value */\n _interpolate(template, params) {\n return template.replace(/\\{(\\w+)\\}/g, (match, key) => {\n return params[key] !== undefined ? params[key] : match;\n });\n }\n\n /** 复数解析 */\n _resolvePlural(obj, count) {\n if (count === 0 && obj.zero) return obj.zero;\n if (count === 1 && obj.one) return obj.one;\n if (obj.other) return obj.other;\n // 中文通常不区分单复数\n return obj.other || obj.one || Object.values(obj)[0] || '';\n }\n\n /** 深合并对象 */\n _deepMerge(target, source) {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n if (\n source[key] && typeof source[key] === 'object' && !Array.isArray(source[key]) &&\n result[key] && typeof result[key] === 'object' && !Array.isArray(result[key])\n ) {\n result[key] = this._deepMerge(result[key], source[key]);\n } else {\n result[key] = source[key];\n }\n }\n return result;\n }\n\n /** 重置 */\n reset() {\n this._messages = {};\n this._listeners = [];\n this._loading.clear();\n this.locale = this._fallback;\n }\n\n // ============ 隐私合规 ============\n\n /**\n * 清除用户语言偏好 — GDPR 本地数据清理\n * 仅清除 localStorage 中的语言偏好记录\n */\n clearUserPreference() {\n if (typeof localStorage !== 'undefined') {\n localStorage.removeItem('qbit_locale');\n }\n this.locale = this._fallback;\n // 恢复 HTML 属性\n if (typeof document !== 'undefined') {\n document.documentElement.lang = this._fallback;\n document.documentElement.dir = 'ltr';\n }\n return true;\n }\n\n /**\n * 获取隐私数据声明\n */\n getDataDisclosure() {\n return {\n sdk: '@quantabit/i18n-sdk',\n privacyLevel: 'essential',\n consentRequired: false,\n collected: [\n { type: 'locale_preference', description: 'User language choice (e.g. \"en\", \"zh\")', retention: 'Until cleared', storage: 'localStorage' },\n ],\n note: 'Language preference is essential for UI rendering and does not contain PII.',\n gdprCapabilities: ['delete'],\n };\n }\n}\n","/**\n * I18n SDK - 国际化\n */\n\nexport const zh = {\n i18n: {\n title: '语言设置',\n currentLanguage: '当前语言',\n languages: {\n zh: '简体中文',\n en: 'English',\n ja: '日本語',\n ko: '한국어',\n },\n actions: {\n change: '切换语言',\n save: '保存',\n },\n messages: {\n changed: '语言已切换',\n },\n },\n};\n\nexport const en = {\n i18n: {\n title: 'Language Settings',\n currentLanguage: 'Current Language',\n languages: {\n zh: '简体中文',\n en: 'English',\n ja: '日本語',\n ko: '한국어',\n },\n actions: {\n change: 'Change Language',\n save: 'Save',\n },\n messages: {\n changed: 'Language changed',\n },\n },\n};\n\nexport default { zh, en };\n","import React,{createContext,useContext,useState,useCallback,useMemo,useEffect}from'react';\nimport{I18nManager}from'../core/I18nManager';\nconst I18nContext=createContext(null);\n\nexport function I18nProvider({messages={},defaultLocale='en',fallbackLocale='en',children}){\n const manager=useMemo(()=>new I18nManager({messages,defaultLocale,fallbackLocale}),[]);\n const[locale,setLocaleState]=useState(defaultLocale);\n useEffect(()=>{return manager.onChange(l=>setLocaleState(l));},[manager]);\n const setLocale=useCallback(l=>manager.setLocale(l),[manager]);\n const t=useCallback((key,params)=>manager.t(key,params),[locale,manager]);\n const value=useMemo(()=>({locale,setLocale,t,availableLocales:manager.availableLocales,manager}),[locale,setLocale,t,manager]);\n return<I18nContext.Provider value={value}>{children}</I18nContext.Provider>;\n}\n\nexport function useI18n(){return useContext(I18nContext);}\nexport function useTranslation(){const ctx=useContext(I18nContext);return ctx?.t||(k=>k);}\n","import React from'react';\nimport{useI18n}from'./I18nProvider';\nconst FLAGS={en:'🇬🇧',zh:'🇨🇳',ja:'🇯🇵',ko:'🇰🇷',es:'🇪🇸',fr:'🇫🇷',de:'🇩🇪',pt:'🇧🇷',ru:'🇷🇺',ar:'🇸🇦'};\nexport function LanguageSwitcher({variant='dropdown',showFlag=true,showLabel=true,className=''}){\n const{locale,setLocale,availableLocales}=useI18n()||{};\n if(!availableLocales)return null;\n if(variant==='pills'){\n return(<div className={`qi18n-pills ${className}`} style={{display:'flex',gap:4,background:'rgba(128,128,128,0.06)',borderRadius:8,padding:3}}>\n {availableLocales.map(l=>(<button key={l} onClick={()=>setLocale(l)}\n style={{padding:'4px 12px',borderRadius:6,border:'none',background:l===locale?'#fff':'transparent',\n color:l===locale?'#18181b':'#71717a',fontSize:13,fontWeight:l===locale?600:400,cursor:'pointer',\n boxShadow:l===locale?'0 1px 3px rgba(0,0,0,0.1)':'none',transition:'all 0.2s'}}>\n {showFlag&&FLAGS[l]&&<span style={{marginRight:4}}>{FLAGS[l]}</span>}{showLabel&&l.toUpperCase()}\n </button>))}\n </div>);\n }\n return(<select value={locale} onChange={e=>setLocale(e.target.value)} className={`qi18n-select ${className}`}\n style={{padding:'6px 12px',borderRadius:8,border:'1px solid #e4e4e7',fontSize:13,cursor:'pointer',background:'#fff'}}>\n {availableLocales.map(l=><option key={l} value={l}>{FLAGS[l]||''} {l.toUpperCase()}</option>)}\n </select>);\n}\n","import { I18nManager } from './core/I18nManager';\nimport i18nMessages from './i18n';\n\nexport { I18nProvider, useI18n, useTranslation } from './components/I18nProvider';\nexport { I18nManager } from './core/I18nManager';\nexport { LanguageSwitcher } from './components/LanguageSwitcher';\n\n// SUPPORTED_LANGUAGES\nexport const SUPPORTED_LANGUAGES = ['en', 'zh', 'ja', 'ko'];\n\n// Singleton Instance\nexport const i18n = new I18nManager({\n defaultLocale: 'zh',\n fallbackLocale: 'en',\n messages: i18nMessages\n});\n\n// Shortcut methods wrapped safely\nexport const t = (key, params) => i18n.t(key, params);\nexport const setLanguage = (locale) => i18n.setLocale(locale);\nexport const getLanguage = () => i18n.currentLocale;\nexport const formatDate = (date, format) => i18n.formatDate(date, format);\nexport const formatNumber = (num, format) => i18n.formatNumber(num, format);\nexport const formatCurrency = (num, currency = 'USD') => i18n.formatNumber(num, { style: 'currency', currency });\n"],"names":["I18nManager","constructor","config","locale","defaultLocale","_messages","messages","_listeners","_fallback","fallbackLocale","_loading","Set","_loaders","_dateFormats","_numberFormats","_debug","debug","autoDetect","navigator","browserLang","_detectBrowserLanguage","currentLocale","availableLocales","Object","keys","setLocale","loadLocale","oldLocale","localStorage","setItem","document","documentElement","lang","rtlLocales","dir","includes","forEach","fn","console","warn","join","addMessages","_deepMerge","t","key","params","msg","_getNestedValue","undefined","count","_resolvePlural","_interpolate","exists","registerLoader","loader","has","add","default","err","error","delete","formatDate","date","format","d","Date","presets","short","year","month","day","long","full","weekday","time","hour","minute","datetime","options","Intl","DateTimeFormat","formatNumber","num","decimal","currency","style","percent","minimumFractionDigits","compact","notation","NumberFormat","formatRelative","now","diffMs","getTime","absDiff","Math","abs","units","unit","ms","value","round","RelativeTimeFormat","numeric","absVal","startsWith","onChange","callback","push","filter","f","saved","getItem","language","userLanguage","obj","parts","split","current","part","template","replace","match","zero","one","other","values","target","source","result","Array","isArray","reset","clear","clearUserPreference","removeItem","getDataDisclosure","sdk","privacyLevel","consentRequired","collected","type","description","retention","storage","note","gdprCapabilities","zh","i18n","title","currentLanguage","languages","en","ja","ko","actions","change","save","changed","I18nContext","createContext","I18nProvider","children","manager","useMemo","setLocaleState","useState","useEffect","l","useCallback","React","createElement","Provider","useI18n","useContext","useTranslation","ctx","k","FLAGS","es","fr","de","pt","ru","ar","LanguageSwitcher","variant","showFlag","showLabel","className","display","gap","background","borderRadius","padding","map","onClick","border","color","fontSize","fontWeight","cursor","boxShadow","transition","marginRight","toUpperCase","e","SUPPORTED_LANGUAGES","i18nMessages","setLanguage","getLanguage","formatCurrency"],"mappings":"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"}
@@ -0,0 +1,606 @@
1
+ import React, { useMemo, useState, useEffect, useCallback, useContext, createContext } from 'react';
2
+
3
+ /**
4
+ * @quantabit/i18n-sdk - I18nManager
5
+ *
6
+ * 轻量级国际化管理器
7
+ * 特性:
8
+ * - 多语言消息管理与切换
9
+ * - 嵌套键路径支持 (e.g. 'nav.home')
10
+ * - 参数插值 ({name} → 'Tom')
11
+ * - 复数形式支持
12
+ * - 回退语言链
13
+ * - 语言自动检测 (浏览器偏好)
14
+ * - 懒加载语言包
15
+ * - 变更事件监听
16
+ */
17
+ class I18nManager {
18
+ constructor(config = {}) {
19
+ this.locale = config.defaultLocale || 'en';
20
+ this._messages = config.messages || {};
21
+ this._listeners = [];
22
+ this._fallback = config.fallbackLocale || 'en';
23
+ this._loading = new Set(); // 正在加载的语言包
24
+ this._loaders = {}; // 语言包加载器
25
+ this._dateFormats = {}; // 日期格式化配置
26
+ this._numberFormats = {}; // 数字格式化配置
27
+ this._debug = config.debug || false;
28
+
29
+ // 自动检测浏览器语言
30
+ if (config.autoDetect !== false && typeof navigator !== 'undefined') {
31
+ const browserLang = this._detectBrowserLanguage();
32
+ if (browserLang && this._messages[browserLang]) {
33
+ this.locale = browserLang;
34
+ }
35
+ }
36
+ }
37
+
38
+ // ============ 基础 API ============
39
+
40
+ /** 当前语言代码 */
41
+ get currentLocale() {
42
+ return this.locale;
43
+ }
44
+
45
+ /** 可用语言列表 */
46
+ get availableLocales() {
47
+ return Object.keys(this._messages);
48
+ }
49
+
50
+ /**
51
+ * 切换语言
52
+ * @param {string} locale - 语言代码
53
+ * @returns {Promise<boolean>} 是否成功
54
+ */
55
+ async setLocale(locale) {
56
+ // 如果语言包不存在且有加载器,尝试懒加载
57
+ if (!this._messages[locale] && this._loaders[locale]) {
58
+ await this.loadLocale(locale);
59
+ }
60
+ if (this._messages[locale]) {
61
+ const oldLocale = this.locale;
62
+ this.locale = locale;
63
+
64
+ // 保存到浏览器
65
+ if (typeof localStorage !== 'undefined') {
66
+ try {
67
+ localStorage.setItem('qbit_locale', locale);
68
+ } catch {}
69
+ }
70
+
71
+ // 设置 HTML lang 属性
72
+ if (typeof document !== 'undefined') {
73
+ document.documentElement.lang = locale;
74
+ // RTL 语言支持
75
+ const rtlLocales = ['ar', 'he', 'fa', 'ur'];
76
+ document.documentElement.dir = rtlLocales.includes(locale) ? 'rtl' : 'ltr';
77
+ }
78
+
79
+ // 通知监听器
80
+ this._listeners.forEach(fn => fn(locale, oldLocale));
81
+ return true;
82
+ }
83
+ if (this._debug) {
84
+ console.warn(`[i18n] 语言 "${locale}" 不可用。可用语言: ${this.availableLocales.join(', ')}`);
85
+ }
86
+ return false;
87
+ }
88
+
89
+ /**
90
+ * 添加语言消息
91
+ * @param {string} locale - 语言代码
92
+ * @param {Object} messages - 消息对象(支持嵌套)
93
+ */
94
+ addMessages(locale, messages) {
95
+ this._messages[locale] = this._deepMerge(this._messages[locale] || {}, messages);
96
+ }
97
+
98
+ /**
99
+ * 翻译 — 核心 API
100
+ * @param {string} key - 翻译键(支持嵌套 'nav.home')
101
+ * @param {Object} params - 插值参数
102
+ * @returns {string} 翻译结果
103
+ *
104
+ * @example
105
+ * i18n.t('greeting', { name: 'Tom' }) // "Hello, Tom!"
106
+ * i18n.t('items', { count: 3 }) // "3 items" (复数)
107
+ * i18n.t('nav.settings.privacy') // 嵌套键路径
108
+ */
109
+ t(key, params = {}) {
110
+ // 1. 查找当前语言
111
+ let msg = this._getNestedValue(this._messages[this.locale], key);
112
+
113
+ // 2. 回退到默认语言
114
+ if (msg === undefined || msg === null) {
115
+ msg = this._getNestedValue(this._messages[this._fallback], key);
116
+ }
117
+
118
+ // 3. 都找不到,返回键名本身(开发友好)
119
+ if (msg === undefined || msg === null) {
120
+ if (this._debug) {
121
+ console.warn(`[i18n] 缺失翻译: "${key}" (${this.locale})`);
122
+ }
123
+ return key;
124
+ }
125
+
126
+ // 4. 复数处理
127
+ if (typeof msg === 'object' && params.count !== undefined) {
128
+ msg = this._resolvePlural(msg, params.count);
129
+ }
130
+
131
+ // 5. 参数插值
132
+ if (typeof msg === 'string' && params) {
133
+ return this._interpolate(msg, params);
134
+ }
135
+ return msg;
136
+ }
137
+
138
+ /**
139
+ * 检查翻译键是否存在
140
+ * @param {string} key - 翻译键
141
+ * @returns {boolean}
142
+ */
143
+ exists(key) {
144
+ return this._getNestedValue(this._messages[this.locale], key) !== undefined;
145
+ }
146
+
147
+ // ============ 语言包管理 ============
148
+
149
+ /**
150
+ * 注册语言包懒加载器
151
+ * @param {string} locale - 语言代码
152
+ * @param {Function} loader - 异步加载函数,返回 Promise<messages>
153
+ *
154
+ * @example
155
+ * i18n.registerLoader('ja', () => import('./locales/ja.json'))
156
+ */
157
+ registerLoader(locale, loader) {
158
+ this._loaders[locale] = loader;
159
+ }
160
+
161
+ /**
162
+ * 懒加载语言包
163
+ * @param {string} locale - 语言代码
164
+ */
165
+ async loadLocale(locale) {
166
+ if (this._messages[locale] || this._loading.has(locale)) return;
167
+ const loader = this._loaders[locale];
168
+ if (!loader) {
169
+ if (this._debug) console.warn(`[i18n] 无 "${locale}" 加载器`);
170
+ return;
171
+ }
172
+ this._loading.add(locale);
173
+ try {
174
+ const messages = await loader();
175
+ // 兼顾 ES Module default export
176
+ this.addMessages(locale, messages.default || messages);
177
+ } catch (err) {
178
+ console.error(`[i18n] 加载 "${locale}" 失败:`, err);
179
+ } finally {
180
+ this._loading.delete(locale);
181
+ }
182
+ }
183
+
184
+ // ============ 格式化 ============
185
+
186
+ /**
187
+ * 格式化日期
188
+ * @param {Date|number|string} date - 日期
189
+ * @param {string} format - 格式名 ('short', 'long', 'full') 或自定义 Intl options
190
+ */
191
+ formatDate(date, format = 'short') {
192
+ const d = date instanceof Date ? date : new Date(date);
193
+ const presets = {
194
+ short: {
195
+ year: 'numeric',
196
+ month: '2-digit',
197
+ day: '2-digit'
198
+ },
199
+ long: {
200
+ year: 'numeric',
201
+ month: 'long',
202
+ day: 'numeric'
203
+ },
204
+ full: {
205
+ year: 'numeric',
206
+ month: 'long',
207
+ day: 'numeric',
208
+ weekday: 'long'
209
+ },
210
+ time: {
211
+ hour: '2-digit',
212
+ minute: '2-digit'
213
+ },
214
+ datetime: {
215
+ year: 'numeric',
216
+ month: 'short',
217
+ day: 'numeric',
218
+ hour: '2-digit',
219
+ minute: '2-digit'
220
+ }
221
+ };
222
+ const options = typeof format === 'string' ? presets[format] || presets.short : format;
223
+ return new Intl.DateTimeFormat(this.locale, options).format(d);
224
+ }
225
+
226
+ /**
227
+ * 格式化数字
228
+ * @param {number} num - 数字
229
+ * @param {string|Object} format - 格式名 ('decimal', 'currency', 'percent') 或自定义
230
+ */
231
+ formatNumber(num, format = 'decimal') {
232
+ const presets = {
233
+ decimal: {},
234
+ currency: {
235
+ style: 'currency',
236
+ currency: 'USD'
237
+ },
238
+ percent: {
239
+ style: 'percent',
240
+ minimumFractionDigits: 1
241
+ },
242
+ compact: {
243
+ notation: 'compact'
244
+ }
245
+ };
246
+ const options = typeof format === 'string' ? presets[format] || {} : format;
247
+ return new Intl.NumberFormat(this.locale, options).format(num);
248
+ }
249
+
250
+ /**
251
+ * 相对时间格式化
252
+ * @param {Date|number} date - 目标时间
253
+ */
254
+ formatRelative(date) {
255
+ const d = date instanceof Date ? date : new Date(date);
256
+ const now = Date.now();
257
+ const diffMs = d.getTime() - now;
258
+ const absDiff = Math.abs(diffMs);
259
+ const units = [{
260
+ unit: 'year',
261
+ ms: 31536000000
262
+ }, {
263
+ unit: 'month',
264
+ ms: 2592000000
265
+ }, {
266
+ unit: 'week',
267
+ ms: 604800000
268
+ }, {
269
+ unit: 'day',
270
+ ms: 86400000
271
+ }, {
272
+ unit: 'hour',
273
+ ms: 3600000
274
+ }, {
275
+ unit: 'minute',
276
+ ms: 60000
277
+ }, {
278
+ unit: 'second',
279
+ ms: 1000
280
+ }];
281
+ for (const {
282
+ unit,
283
+ ms
284
+ } of units) {
285
+ if (absDiff >= ms) {
286
+ const value = Math.round(diffMs / ms);
287
+ try {
288
+ return new Intl.RelativeTimeFormat(this.locale, {
289
+ numeric: 'auto'
290
+ }).format(value, unit);
291
+ } catch {
292
+ // Fallback: 简单文本
293
+ const absVal = Math.abs(value);
294
+ return diffMs < 0 ? `${absVal} ${unit}(s) ago` : `in ${absVal} ${unit}(s)`;
295
+ }
296
+ }
297
+ }
298
+ return this.locale.startsWith('zh') ? '刚刚' : 'just now';
299
+ }
300
+
301
+ // ============ 事件监听 ============
302
+
303
+ /**
304
+ * 监听语言变更
305
+ * @param {Function} callback - (newLocale, oldLocale) => void
306
+ * @returns {Function} 取消监听函数
307
+ */
308
+ onChange(callback) {
309
+ this._listeners.push(callback);
310
+ return () => {
311
+ this._listeners = this._listeners.filter(f => f !== callback);
312
+ };
313
+ }
314
+
315
+ // ============ 内部方法 ============
316
+
317
+ /** 检测浏览器语言偏好 */
318
+ _detectBrowserLanguage() {
319
+ // 先查 localStorage
320
+ try {
321
+ const saved = localStorage.getItem('qbit_locale');
322
+ if (saved) return saved;
323
+ } catch {}
324
+
325
+ // 浏览器语言
326
+ const lang = navigator.language || navigator.userLanguage;
327
+ return lang;
328
+ }
329
+
330
+ /** 嵌套键路径取值 (e.g. 'nav.home' → messages.nav.home) */
331
+ _getNestedValue(obj, key) {
332
+ if (!obj || !key) return undefined;
333
+
334
+ // 先精确匹配
335
+ if (obj[key] !== undefined) return obj[key];
336
+
337
+ // 嵌套路径
338
+ const parts = key.split('.');
339
+ let current = obj;
340
+ for (const part of parts) {
341
+ if (current === null || current === undefined || typeof current !== 'object') {
342
+ return undefined;
343
+ }
344
+ current = current[part];
345
+ }
346
+ return current;
347
+ }
348
+
349
+ /** 参数插值 {name} → value */
350
+ _interpolate(template, params) {
351
+ return template.replace(/\{(\w+)\}/g, (match, key) => {
352
+ return params[key] !== undefined ? params[key] : match;
353
+ });
354
+ }
355
+
356
+ /** 复数解析 */
357
+ _resolvePlural(obj, count) {
358
+ if (count === 0 && obj.zero) return obj.zero;
359
+ if (count === 1 && obj.one) return obj.one;
360
+ if (obj.other) return obj.other;
361
+ // 中文通常不区分单复数
362
+ return obj.other || obj.one || Object.values(obj)[0] || '';
363
+ }
364
+
365
+ /** 深合并对象 */
366
+ _deepMerge(target, source) {
367
+ const result = {
368
+ ...target
369
+ };
370
+ for (const key of Object.keys(source)) {
371
+ if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key]) && result[key] && typeof result[key] === 'object' && !Array.isArray(result[key])) {
372
+ result[key] = this._deepMerge(result[key], source[key]);
373
+ } else {
374
+ result[key] = source[key];
375
+ }
376
+ }
377
+ return result;
378
+ }
379
+
380
+ /** 重置 */
381
+ reset() {
382
+ this._messages = {};
383
+ this._listeners = [];
384
+ this._loading.clear();
385
+ this.locale = this._fallback;
386
+ }
387
+
388
+ // ============ 隐私合规 ============
389
+
390
+ /**
391
+ * 清除用户语言偏好 — GDPR 本地数据清理
392
+ * 仅清除 localStorage 中的语言偏好记录
393
+ */
394
+ clearUserPreference() {
395
+ if (typeof localStorage !== 'undefined') {
396
+ localStorage.removeItem('qbit_locale');
397
+ }
398
+ this.locale = this._fallback;
399
+ // 恢复 HTML 属性
400
+ if (typeof document !== 'undefined') {
401
+ document.documentElement.lang = this._fallback;
402
+ document.documentElement.dir = 'ltr';
403
+ }
404
+ return true;
405
+ }
406
+
407
+ /**
408
+ * 获取隐私数据声明
409
+ */
410
+ getDataDisclosure() {
411
+ return {
412
+ sdk: '@quantabit/i18n-sdk',
413
+ privacyLevel: 'essential',
414
+ consentRequired: false,
415
+ collected: [{
416
+ type: 'locale_preference',
417
+ description: 'User language choice (e.g. "en", "zh")',
418
+ retention: 'Until cleared',
419
+ storage: 'localStorage'
420
+ }],
421
+ note: 'Language preference is essential for UI rendering and does not contain PII.',
422
+ gdprCapabilities: ['delete']
423
+ };
424
+ }
425
+ }
426
+
427
+ /**
428
+ * I18n SDK - 国际化
429
+ */
430
+
431
+ const zh = {
432
+ i18n: {
433
+ title: '语言设置',
434
+ currentLanguage: '当前语言',
435
+ languages: {
436
+ zh: '简体中文',
437
+ en: 'English',
438
+ ja: '日本語',
439
+ ko: '한국어'
440
+ },
441
+ actions: {
442
+ change: '切换语言',
443
+ save: '保存'
444
+ },
445
+ messages: {
446
+ changed: '语言已切换'
447
+ }
448
+ }
449
+ };
450
+ const en = {
451
+ i18n: {
452
+ title: 'Language Settings',
453
+ currentLanguage: 'Current Language',
454
+ languages: {
455
+ zh: '简体中文',
456
+ en: 'English',
457
+ ja: '日本語',
458
+ ko: '한국어'
459
+ },
460
+ actions: {
461
+ change: 'Change Language',
462
+ save: 'Save'
463
+ },
464
+ messages: {
465
+ changed: 'Language changed'
466
+ }
467
+ }
468
+ };
469
+ var i18nMessages = {
470
+ zh,
471
+ en
472
+ };
473
+
474
+ const I18nContext = /*#__PURE__*/createContext(null);
475
+ function I18nProvider({
476
+ messages = {},
477
+ defaultLocale = 'en',
478
+ fallbackLocale = 'en',
479
+ children
480
+ }) {
481
+ const manager = useMemo(() => new I18nManager({
482
+ messages,
483
+ defaultLocale,
484
+ fallbackLocale
485
+ }), []);
486
+ const [locale, setLocaleState] = useState(defaultLocale);
487
+ useEffect(() => {
488
+ return manager.onChange(l => setLocaleState(l));
489
+ }, [manager]);
490
+ const setLocale = useCallback(l => manager.setLocale(l), [manager]);
491
+ const t = useCallback((key, params) => manager.t(key, params), [locale, manager]);
492
+ const value = useMemo(() => ({
493
+ locale,
494
+ setLocale,
495
+ t,
496
+ availableLocales: manager.availableLocales,
497
+ manager
498
+ }), [locale, setLocale, t, manager]);
499
+ return /*#__PURE__*/React.createElement(I18nContext.Provider, {
500
+ value: value
501
+ }, children);
502
+ }
503
+ function useI18n() {
504
+ return useContext(I18nContext);
505
+ }
506
+ function useTranslation() {
507
+ const ctx = useContext(I18nContext);
508
+ return ctx?.t || (k => k);
509
+ }
510
+
511
+ const FLAGS = {
512
+ en: '🇬🇧',
513
+ zh: '🇨🇳',
514
+ ja: '🇯🇵',
515
+ ko: '🇰🇷',
516
+ es: '🇪🇸',
517
+ fr: '🇫🇷',
518
+ de: '🇩🇪',
519
+ pt: '🇧🇷',
520
+ ru: '🇷🇺',
521
+ ar: '🇸🇦'
522
+ };
523
+ function LanguageSwitcher({
524
+ variant = 'dropdown',
525
+ showFlag = true,
526
+ showLabel = true,
527
+ className = ''
528
+ }) {
529
+ const {
530
+ locale,
531
+ setLocale,
532
+ availableLocales
533
+ } = useI18n() || {};
534
+ if (!availableLocales) return null;
535
+ if (variant === 'pills') {
536
+ return /*#__PURE__*/React.createElement("div", {
537
+ className: `qi18n-pills ${className}`,
538
+ style: {
539
+ display: 'flex',
540
+ gap: 4,
541
+ background: 'rgba(128,128,128,0.06)',
542
+ borderRadius: 8,
543
+ padding: 3
544
+ }
545
+ }, availableLocales.map(l => /*#__PURE__*/React.createElement("button", {
546
+ key: l,
547
+ onClick: () => setLocale(l),
548
+ style: {
549
+ padding: '4px 12px',
550
+ borderRadius: 6,
551
+ border: 'none',
552
+ background: l === locale ? '#fff' : 'transparent',
553
+ color: l === locale ? '#18181b' : '#71717a',
554
+ fontSize: 13,
555
+ fontWeight: l === locale ? 600 : 400,
556
+ cursor: 'pointer',
557
+ boxShadow: l === locale ? '0 1px 3px rgba(0,0,0,0.1)' : 'none',
558
+ transition: 'all 0.2s'
559
+ }
560
+ }, showFlag && FLAGS[l] && /*#__PURE__*/React.createElement("span", {
561
+ style: {
562
+ marginRight: 4
563
+ }
564
+ }, FLAGS[l]), showLabel && l.toUpperCase())));
565
+ }
566
+ return /*#__PURE__*/React.createElement("select", {
567
+ value: locale,
568
+ onChange: e => setLocale(e.target.value),
569
+ className: `qi18n-select ${className}`,
570
+ style: {
571
+ padding: '6px 12px',
572
+ borderRadius: 8,
573
+ border: '1px solid #e4e4e7',
574
+ fontSize: 13,
575
+ cursor: 'pointer',
576
+ background: '#fff'
577
+ }
578
+ }, availableLocales.map(l => /*#__PURE__*/React.createElement("option", {
579
+ key: l,
580
+ value: l
581
+ }, FLAGS[l] || '', " ", l.toUpperCase())));
582
+ }
583
+
584
+ // SUPPORTED_LANGUAGES
585
+ const SUPPORTED_LANGUAGES = ['en', 'zh', 'ja', 'ko'];
586
+
587
+ // Singleton Instance
588
+ const i18n = new I18nManager({
589
+ defaultLocale: 'zh',
590
+ fallbackLocale: 'en',
591
+ messages: i18nMessages
592
+ });
593
+
594
+ // Shortcut methods wrapped safely
595
+ const t = (key, params) => i18n.t(key, params);
596
+ const setLanguage = locale => i18n.setLocale(locale);
597
+ const getLanguage = () => i18n.currentLocale;
598
+ const formatDate = (date, format) => i18n.formatDate(date, format);
599
+ const formatNumber = (num, format) => i18n.formatNumber(num, format);
600
+ const formatCurrency = (num, currency = 'USD') => i18n.formatNumber(num, {
601
+ style: 'currency',
602
+ currency
603
+ });
604
+
605
+ export { I18nManager, I18nProvider, LanguageSwitcher, SUPPORTED_LANGUAGES, formatCurrency, formatDate, formatNumber, getLanguage, i18n, setLanguage, t, useI18n, useTranslation };
606
+ //# sourceMappingURL=index.esm.js.map