@qhr123/sa2kit 0.4.1 → 0.4.2

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.
@@ -1,3 +1,5 @@
1
+ import React from 'react';
2
+
1
3
  /**
2
4
  * i18n 类型定义
3
5
  */
@@ -377,4 +379,26 @@ declare class ElectronI18nAdapter implements I18nAdapter {
377
379
  private normalizeLocale;
378
380
  }
379
381
 
380
- export { ElectronI18nAdapter, type I18nAdapter, type I18nConfig, type I18nInstance, type Locale, type LocaleResources, ReactNativeI18nAdapter, TaroI18nAdapter, type TranslateOptions, type TranslationKey, type TranslationValue, type Translations, WebI18nAdapter, createI18n, _default as enUS, getI18n, initI18n, t, useLocale, useTranslation, _default$1 as zhCN };
382
+ /**
383
+ * 语言切换组件
384
+ * 支持多种样式:按钮组、下拉菜单、图标按钮
385
+ * 使用 Tailwind CSS 样式
386
+ */
387
+
388
+ interface LanguageSwitcherProps {
389
+ variant?: 'buttons' | 'dropdown' | 'icon';
390
+ className?: string;
391
+ onLanguageChange?: (locale: Locale) => void;
392
+ }
393
+ interface LanguageOption {
394
+ locale: Locale;
395
+ label: string;
396
+ flag: string;
397
+ }
398
+ /**
399
+ * 语言切换器主组件
400
+ * 根据 variant 自动选择样式
401
+ */
402
+ declare function LanguageSwitcher({ variant, className, onLanguageChange, }: LanguageSwitcherProps): React.JSX.Element;
403
+
404
+ export { ElectronI18nAdapter, type I18nAdapter, type I18nConfig, type I18nInstance, type LanguageOption, LanguageSwitcher, type LanguageSwitcherProps, type Locale, type LocaleResources, ReactNativeI18nAdapter, TaroI18nAdapter, type TranslateOptions, type TranslationKey, type TranslationValue, type Translations, WebI18nAdapter, createI18n, _default as enUS, getI18n, initI18n, t, useLocale, useTranslation, _default$1 as zhCN };
@@ -1,3 +1,5 @@
1
+ import React from 'react';
2
+
1
3
  /**
2
4
  * i18n 类型定义
3
5
  */
@@ -377,4 +379,26 @@ declare class ElectronI18nAdapter implements I18nAdapter {
377
379
  private normalizeLocale;
378
380
  }
379
381
 
380
- export { ElectronI18nAdapter, type I18nAdapter, type I18nConfig, type I18nInstance, type Locale, type LocaleResources, ReactNativeI18nAdapter, TaroI18nAdapter, type TranslateOptions, type TranslationKey, type TranslationValue, type Translations, WebI18nAdapter, createI18n, _default as enUS, getI18n, initI18n, t, useLocale, useTranslation, _default$1 as zhCN };
382
+ /**
383
+ * 语言切换组件
384
+ * 支持多种样式:按钮组、下拉菜单、图标按钮
385
+ * 使用 Tailwind CSS 样式
386
+ */
387
+
388
+ interface LanguageSwitcherProps {
389
+ variant?: 'buttons' | 'dropdown' | 'icon';
390
+ className?: string;
391
+ onLanguageChange?: (locale: Locale) => void;
392
+ }
393
+ interface LanguageOption {
394
+ locale: Locale;
395
+ label: string;
396
+ flag: string;
397
+ }
398
+ /**
399
+ * 语言切换器主组件
400
+ * 根据 variant 自动选择样式
401
+ */
402
+ declare function LanguageSwitcher({ variant, className, onLanguageChange, }: LanguageSwitcherProps): React.JSX.Element;
403
+
404
+ export { ElectronI18nAdapter, type I18nAdapter, type I18nConfig, type I18nInstance, type LanguageOption, LanguageSwitcher, type LanguageSwitcherProps, type Locale, type LocaleResources, ReactNativeI18nAdapter, TaroI18nAdapter, type TranslateOptions, type TranslationKey, type TranslationValue, type Translations, WebI18nAdapter, createI18n, _default as enUS, getI18n, initI18n, t, useLocale, useTranslation, _default$1 as zhCN };
@@ -1,7 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkDGUM43GV_js = require('../chunk-DGUM43GV.js');
4
- var react = require('react');
4
+ var React = require('react');
5
+
6
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
+
8
+ var React__default = /*#__PURE__*/_interopDefault(React);
5
9
 
6
10
  // src/i18n/i18n.ts
7
11
  function defaultInterpolate(template, data) {
@@ -87,15 +91,15 @@ function t(key, options) {
87
91
  }
88
92
  function useTranslation() {
89
93
  const i18n = getI18n();
90
- const [locale, setLocaleState] = react.useState(i18n.getLocale());
91
- const t2 = react.useCallback(
94
+ const [locale, setLocaleState] = React.useState(i18n.getLocale());
95
+ const t2 = React.useCallback(
92
96
  (key, options) => {
93
97
  return i18n.t(key, options);
94
98
  },
95
99
  [locale]
96
100
  // locale 改变时重新创建函数
97
101
  );
98
- const setLocale = react.useCallback((newLocale) => {
102
+ const setLocale = React.useCallback((newLocale) => {
99
103
  i18n.setLocale(newLocale);
100
104
  setLocaleState(newLocale);
101
105
  }, []);
@@ -107,8 +111,8 @@ function useTranslation() {
107
111
  }
108
112
  function useLocale() {
109
113
  const i18n = getI18n();
110
- const [locale, setLocaleState] = react.useState(i18n.getLocale());
111
- const setLocale = react.useCallback((newLocale) => {
114
+ const [locale, setLocaleState] = React.useState(i18n.getLocale());
115
+ const setLocale = React.useCallback((newLocale) => {
112
116
  i18n.setLocale(newLocale);
113
117
  setLocaleState(newLocale);
114
118
  }, []);
@@ -531,8 +535,124 @@ var ElectronI18nAdapter = class {
531
535
  return map[locale] || "zh-CN";
532
536
  }
533
537
  };
538
+ var LANGUAGE_OPTIONS = [
539
+ { locale: "zh-CN", label: "\u7B80\u4F53\u4E2D\u6587", flag: "\u{1F1E8}\u{1F1F3}" },
540
+ { locale: "zh-TW", label: "\u7E41\u9AD4\u4E2D\u6587", flag: "\u{1F1F9}\u{1F1FC}" },
541
+ { locale: "en-US", label: "English", flag: "\u{1F1FA}\u{1F1F8}" },
542
+ { locale: "ja-JP", label: "\u65E5\u672C\u8A9E", flag: "\u{1F1EF}\u{1F1F5}" }
543
+ ];
544
+ function LanguageSwitcherButtons({
545
+ className = "",
546
+ onLanguageChange
547
+ }) {
548
+ const { locale, setLocale } = useTranslation();
549
+ const handleChange = (newLocale) => {
550
+ setLocale(newLocale);
551
+ onLanguageChange?.(newLocale);
552
+ };
553
+ return /* @__PURE__ */ React__default.default.createElement("div", { className: `flex gap-2 flex-wrap ${className}` }, LANGUAGE_OPTIONS.map((option) => /* @__PURE__ */ React__default.default.createElement(
554
+ "button",
555
+ {
556
+ key: option.locale,
557
+ onClick: () => handleChange(option.locale),
558
+ className: `
559
+ flex items-center gap-2 px-4 py-2 rounded-lg border-2
560
+ transition-all duration-200 font-medium
561
+ ${locale === option.locale ? "border-blue-500 bg-blue-50 text-blue-700 shadow-md" : "border-gray-300 bg-white text-gray-700 hover:border-blue-300 hover:bg-blue-50"}
562
+ `,
563
+ "aria-label": option.label
564
+ },
565
+ /* @__PURE__ */ React__default.default.createElement("span", { className: "text-xl" }, option.flag),
566
+ /* @__PURE__ */ React__default.default.createElement("span", { className: "text-sm" }, option.label)
567
+ )));
568
+ }
569
+ function LanguageSwitcherDropdown({
570
+ className = "",
571
+ onLanguageChange
572
+ }) {
573
+ const { locale, setLocale, t: t2 } = useTranslation();
574
+ const handleChange = (e) => {
575
+ const newLocale = e.target.value;
576
+ setLocale(newLocale);
577
+ onLanguageChange?.(newLocale);
578
+ };
579
+ return /* @__PURE__ */ React__default.default.createElement("div", { className: `flex flex-col gap-2 ${className}` }, /* @__PURE__ */ React__default.default.createElement("label", { htmlFor: "language-select", className: "text-sm font-medium text-gray-700" }, t2("language.label")), /* @__PURE__ */ React__default.default.createElement(
580
+ "select",
581
+ {
582
+ id: "language-select",
583
+ value: locale,
584
+ onChange: handleChange,
585
+ className: "\n px-4 py-2 rounded-lg border-2 border-gray-300 bg-white\n text-gray-700 font-medium cursor-pointer\n focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500\n hover:border-gray-400 transition-colors duration-200\n ",
586
+ "aria-label": t2("language.label")
587
+ },
588
+ LANGUAGE_OPTIONS.map((option) => /* @__PURE__ */ React__default.default.createElement("option", { key: option.locale, value: option.locale }, option.flag, " ", option.label))
589
+ ));
590
+ }
591
+ function LanguageSwitcherIcon({ className = "", onLanguageChange }) {
592
+ const { locale, setLocale } = useTranslation();
593
+ const [isOpen, setIsOpen] = React__default.default.useState(false);
594
+ const currentOption = LANGUAGE_OPTIONS.find((opt) => opt.locale === locale);
595
+ const handleChange = (newLocale) => {
596
+ setLocale(newLocale);
597
+ setIsOpen(false);
598
+ onLanguageChange?.(newLocale);
599
+ };
600
+ React__default.default.useEffect(() => {
601
+ const handleClickOutside = (event) => {
602
+ const target = event.target;
603
+ if (!target.closest(".language-switcher-icon-wrapper")) {
604
+ setIsOpen(false);
605
+ }
606
+ };
607
+ if (isOpen) {
608
+ document.addEventListener("mousedown", handleClickOutside);
609
+ return () => document.removeEventListener("mousedown", handleClickOutside);
610
+ }
611
+ return void 0;
612
+ }, [isOpen]);
613
+ return /* @__PURE__ */ React__default.default.createElement("div", { className: `relative language-switcher-icon-wrapper ${className}` }, /* @__PURE__ */ React__default.default.createElement(
614
+ "button",
615
+ {
616
+ onClick: () => setIsOpen(!isOpen),
617
+ className: "\n flex items-center gap-2 px-3 py-2 rounded-lg border-2 border-gray-300\n bg-white hover:border-blue-300 hover:bg-blue-50\n transition-all duration-200 cursor-pointer\n focus:outline-none focus:ring-2 focus:ring-blue-500\n ",
618
+ "aria-label": "Switch Language",
619
+ "aria-expanded": isOpen
620
+ },
621
+ /* @__PURE__ */ React__default.default.createElement("span", { className: "text-xl" }, currentOption?.flag),
622
+ /* @__PURE__ */ React__default.default.createElement("span", { className: `text-gray-600 text-xs transition-transform duration-200 ${isOpen ? "rotate-180" : ""}` }, "\u25BC")
623
+ ), isOpen && /* @__PURE__ */ React__default.default.createElement("div", { className: "\n absolute right-0 top-full mt-2 w-48\n bg-white border-2 border-gray-200 rounded-lg shadow-lg\n overflow-hidden z-50\n animate-in fade-in slide-in-from-top-2 duration-200\n " }, LANGUAGE_OPTIONS.map((option) => /* @__PURE__ */ React__default.default.createElement(
624
+ "button",
625
+ {
626
+ key: option.locale,
627
+ onClick: () => handleChange(option.locale),
628
+ className: `
629
+ w-full flex items-center justify-between px-4 py-3
630
+ transition-colors duration-150
631
+ ${locale === option.locale ? "bg-blue-50 text-blue-700" : "text-gray-700 hover:bg-gray-50"}
632
+ `
633
+ },
634
+ /* @__PURE__ */ React__default.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React__default.default.createElement("span", { className: "text-lg" }, option.flag), /* @__PURE__ */ React__default.default.createElement("span", { className: "text-sm font-medium" }, option.label)),
635
+ locale === option.locale && /* @__PURE__ */ React__default.default.createElement("span", { className: "text-blue-600 font-bold" }, "\u2713")
636
+ ))));
637
+ }
638
+ function LanguageSwitcher({
639
+ variant = "buttons",
640
+ className,
641
+ onLanguageChange
642
+ }) {
643
+ switch (variant) {
644
+ case "dropdown":
645
+ return /* @__PURE__ */ React__default.default.createElement(LanguageSwitcherDropdown, { className, onLanguageChange });
646
+ case "icon":
647
+ return /* @__PURE__ */ React__default.default.createElement(LanguageSwitcherIcon, { className, onLanguageChange });
648
+ case "buttons":
649
+ default:
650
+ return /* @__PURE__ */ React__default.default.createElement(LanguageSwitcherButtons, { className, onLanguageChange });
651
+ }
652
+ }
534
653
 
535
654
  exports.ElectronI18nAdapter = ElectronI18nAdapter;
655
+ exports.LanguageSwitcher = LanguageSwitcher;
536
656
  exports.ReactNativeI18nAdapter = ReactNativeI18nAdapter;
537
657
  exports.TaroI18nAdapter = TaroI18nAdapter;
538
658
  exports.WebI18nAdapter = WebI18nAdapter;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/i18n/i18n.ts","../../src/i18n/hooks.ts","../../src/i18n/locales/zh-CN.ts","../../src/i18n/locales/en-US.ts","../../src/i18n/adapters/web.ts","../../src/i18n/adapters/mobile.ts","../../src/i18n/adapters/miniapp.ts","../../src/i18n/adapters/desktop.ts"],"names":["t","useState","useCallback","__require"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * 轻量级 i18n 核心实现\n * 支持:翻译、插值、复数、嵌套键、类型安全\n */\n\nimport type {\n Locale,\n Translations,\n LocaleResources,\n TranslateOptions,\n I18nConfig,\n I18nInstance,\n} from './types';\n\n/**\n * 默认插值函数\n * 支持 {{key}} 格式的变量替换\n */\nfunction defaultInterpolate(template: string, data: Record<string, any>): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key) => {\n return data[key]?.toString() ?? match;\n });\n}\n\n/**\n * 从嵌套对象中获取值\n * 支持 \"user.name\" 这样的路径\n */\nfunction getNestedValue(obj: any, path: string): any {\n const keys = path.split('.');\n let result = obj;\n\n for (const key of keys) {\n if (result && typeof result === 'object' && key in result) {\n result = result[key];\n } else {\n return undefined;\n }\n }\n\n return result;\n}\n\n/**\n * 创建 i18n 实例\n */\nexport function createI18n(config: I18nConfig): I18nInstance {\n let currentLocale: Locale = config.locale;\n const fallbackLocale: Locale = config.fallbackLocale || 'zh-CN';\n const resources: LocaleResources = config.resources || {};\n const interpolate = config.interpolate || defaultInterpolate;\n\n /**\n * 翻译函数\n * @param key 翻译键,支持嵌套 \"common.hello\"\n * @param options 选项\n */\n function t(key: string, options: TranslateOptions = {}): string {\n const { defaultValue, count, context = {} } = options;\n\n // 获取当前语言的翻译\n let translation = getNestedValue(resources[currentLocale], key);\n\n // 如果没有找到,尝试使用 fallback 语言\n if (translation === undefined && currentLocale !== fallbackLocale) {\n translation = getNestedValue(resources[fallbackLocale], key);\n }\n\n // 如果还是没有找到,使用默认值或键名\n if (translation === undefined) {\n return defaultValue || key;\n }\n\n // 如果不是字符串,返回 JSON 字符串\n if (typeof translation !== 'string') {\n return JSON.stringify(translation);\n }\n\n // 处理复数\n if (count !== undefined) {\n const pluralKey = count === 1 ? `${key}_one` : `${key}_other`;\n const pluralTranslation = getNestedValue(resources[currentLocale], pluralKey);\n if (pluralTranslation && typeof pluralTranslation === 'string') {\n translation = pluralTranslation;\n }\n }\n\n // 插值\n const data = { ...context, count };\n return interpolate(translation, data);\n }\n\n /**\n * 设置当前语言\n */\n function setLocale(locale: Locale): void {\n currentLocale = locale;\n }\n\n /**\n * 添加翻译资源\n */\n function addResources(locale: Locale, newResources: Translations): void {\n if (!resources[locale]) {\n resources[locale] = {};\n }\n resources[locale] = {\n ...resources[locale],\n ...newResources,\n };\n }\n\n /**\n * 获取当前语言\n */\n function getLocale(): Locale {\n return currentLocale;\n }\n\n return {\n locale: currentLocale,\n t,\n setLocale,\n addResources,\n getLocale,\n };\n}\n\n/**\n * 全局 i18n 实例(可选)\n */\nlet globalI18n: I18nInstance | null = null;\n\n/**\n * 初始化全局 i18n\n */\nexport function initI18n(config: I18nConfig): I18nInstance {\n globalI18n = createI18n(config);\n return globalI18n;\n}\n\n/**\n * 获取全局 i18n 实例\n */\nexport function getI18n(): I18nInstance {\n if (!globalI18n) {\n throw new Error('i18n not initialized. Call initI18n() first.');\n }\n return globalI18n;\n}\n\n/**\n * 快捷翻译函数\n */\nexport function t(key: string, options?: TranslateOptions): string {\n return getI18n().t(key, options);\n}\n","/**\n * React hooks for i18n\n */\n\nimport { useState, useCallback } from 'react';\nimport { getI18n } from './i18n';\nimport type { Locale, TranslateOptions } from './types';\n\n/**\n * useTranslation Hook\n * React 组件中使用翻译\n */\nexport function useTranslation() {\n const i18n = getI18n();\n const [locale, setLocaleState] = useState<Locale>(i18n.getLocale());\n\n // 翻译函数\n const t = useCallback(\n (key: string, options?: TranslateOptions): string => {\n return i18n.t(key, options);\n },\n [locale] // locale 改变时重新创建函数\n );\n\n // 切换语言\n const setLocale = useCallback((newLocale: Locale) => {\n i18n.setLocale(newLocale);\n setLocaleState(newLocale);\n }, []);\n\n return {\n t,\n locale,\n setLocale,\n };\n}\n\n/**\n * useLocale Hook\n * 只获取和设置语言,不包含翻译函数\n */\nexport function useLocale() {\n const i18n = getI18n();\n const [locale, setLocaleState] = useState<Locale>(i18n.getLocale());\n\n const setLocale = useCallback((newLocale: Locale) => {\n i18n.setLocale(newLocale);\n setLocaleState(newLocale);\n }, []);\n\n return {\n locale,\n setLocale,\n };\n}\n","/**\n * 简体中文翻译\n */\n\nexport default {\n // ==================== 应用信息 ====================\n app: {\n name: 'LyricNote',\n fullName: 'LyricNote - 歌词笔记',\n icon: '🎵',\n description: '一个强大的歌词和笔记管理应用',\n author: 'LyricNote Team',\n copyright: `© ${new Date().getFullYear()} LyricNote`,\n version: '1.0.0',\n },\n\n // ==================== 应用标题 ====================\n titles: {\n main: '🎵 LyricNote',\n admin: 'LyricNote 管理后台',\n withVersion: 'LyricNote v1.0.0',\n welcome: '欢迎使用 LyricNote',\n about: '关于 LyricNote',\n },\n\n // ==================== 通用文案 ====================\n common: {\n hello: '你好',\n welcome: '欢迎',\n confirm: '确认',\n cancel: '取消',\n save: '保存',\n delete: '删除',\n edit: '编辑',\n back: '返回',\n next: '下一步',\n submit: '提交',\n finish: '完成',\n loading: '加载中...',\n success: '操作成功',\n error: '操作失败',\n retry: '重试',\n empty: '暂无数据',\n },\n\n // ==================== 导航菜单 ====================\n nav: {\n home: '首页',\n lyrics: '歌词',\n create: '创作',\n collection: '收藏',\n profile: '我的',\n settings: '设置',\n history: '历史',\n logout: '退出登录',\n },\n\n // ==================== 用户相关 ====================\n user: {\n login: '登录',\n register: '注册',\n username: '用户名',\n password: '密码',\n email: '邮箱',\n phone: '手机号',\n nickname: '昵称',\n },\n\n // ==================== 页面标题和描述 ====================\n pages: {\n home: {\n title: '首页',\n description: '一个强大的歌词和笔记管理应用',\n },\n profile: {\n title: '个人中心',\n description: '管理您的个人信息和偏好设置',\n },\n admin: {\n title: 'LyricNote 管理后台',\n description: '系统管理和数据统计',\n },\n login: {\n title: '登录',\n description: '登录到 LyricNote',\n },\n },\n\n // ==================== 表单验证 ====================\n validation: {\n required: '{{field}}不能为空',\n invalid_email: '邮箱格式不正确',\n password_too_short: '密码至少需要{{count}}个字符',\n password_weak: '密码强度不够',\n passwords_not_match: '两次密码不一致',\n },\n\n // ==================== 状态提示 ====================\n status: {\n loading: '加载中...',\n success: '操作成功',\n error: '操作失败',\n empty: '暂无数据',\n network_error: '网络错误,请稍后重试',\n },\n\n // ==================== 错误消息 ====================\n errors: {\n network: '网络错误,请稍后重试',\n server: '服务器错误',\n unauthorized: '未授权,请先登录',\n not_found: '未找到相关内容',\n unknown: '未知错误',\n },\n\n // ==================== 成功消息 ====================\n success: {\n saved: '保存成功',\n deleted: '删除成功',\n updated: '更新成功',\n created: '创建成功',\n },\n\n // ==================== 语言设置 ====================\n language: {\n label: '语言',\n zh_cn: '简体中文',\n zh_tw: '繁體中文',\n en_us: 'English',\n ja_jp: '日本語',\n },\n} as const;\n","/**\n * English translations\n */\n\nexport default {\n // ==================== App Information ====================\n app: {\n name: 'LyricNote',\n fullName: 'LyricNote - Lyrics & Notes',\n icon: '🎵',\n description: 'A powerful lyrics and notes management app',\n author: 'LyricNote Team',\n copyright: `© ${new Date().getFullYear()} LyricNote`,\n version: '1.0.0',\n },\n\n // ==================== App Titles ====================\n titles: {\n main: '🎵 LyricNote',\n admin: 'LyricNote Admin',\n withVersion: 'LyricNote v1.0.0',\n welcome: 'Welcome to LyricNote',\n about: 'About LyricNote',\n },\n\n // ==================== Common ====================\n common: {\n hello: 'Hello',\n welcome: 'Welcome',\n confirm: 'Confirm',\n cancel: 'Cancel',\n save: 'Save',\n delete: 'Delete',\n edit: 'Edit',\n back: 'Back',\n next: 'Next',\n submit: 'Submit',\n finish: 'Finish',\n loading: 'Loading...',\n success: 'Success',\n error: 'Error',\n retry: 'Retry',\n empty: 'No data',\n },\n\n // ==================== Navigation ====================\n nav: {\n home: 'Home',\n lyrics: 'Lyrics',\n create: 'Create',\n collection: 'Collection',\n profile: 'Profile',\n settings: 'Settings',\n history: 'History',\n logout: 'Logout',\n },\n\n // ==================== User ====================\n user: {\n login: 'Login',\n register: 'Register',\n username: 'Username',\n password: 'Password',\n email: 'Email',\n phone: 'Phone',\n nickname: 'Nickname',\n },\n\n // ==================== Pages ====================\n pages: {\n home: {\n title: 'Home',\n description: 'A powerful lyrics and notes management app',\n },\n profile: {\n title: 'Profile',\n description: 'Manage your personal information and preferences',\n },\n admin: {\n title: 'LyricNote Admin',\n description: 'System management and data statistics',\n },\n login: {\n title: 'Login',\n description: 'Login to LyricNote',\n },\n },\n\n // ==================== Form Validation ====================\n validation: {\n required: '{{field}} is required',\n invalid_email: 'Invalid email format',\n password_too_short: 'Password must be at least {{count}} characters',\n password_weak: 'Password is too weak',\n passwords_not_match: 'Passwords do not match',\n },\n\n // ==================== Status Messages ====================\n status: {\n loading: 'Loading...',\n success: 'Success',\n error: 'Error',\n empty: 'No data',\n network_error: 'Network error, please try again later',\n },\n\n // ==================== Error Messages ====================\n errors: {\n network: 'Network error, please try again later',\n server: 'Server error',\n unauthorized: 'Unauthorized, please login first',\n not_found: 'Not found',\n unknown: 'Unknown error',\n },\n\n // ==================== Success Messages ====================\n success: {\n saved: 'Saved successfully',\n deleted: 'Deleted successfully',\n updated: 'Updated successfully',\n created: 'Created successfully',\n },\n\n // ==================== Language Settings ====================\n language: {\n label: 'Language',\n zh_cn: '简体中文',\n zh_tw: '繁體中文',\n en_us: 'English',\n ja_jp: '日本語',\n },\n} as const;\n","/**\n * Web 平台适配器\n * 用于浏览器环境的语言检测和存储\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * Web 平台适配器\n * 使用 localStorage 存储语言偏好\n */\nexport class WebI18nAdapter implements I18nAdapter {\n private storageKey = 'app_locale';\n\n getSystemLocale(): Locale {\n if (typeof navigator === 'undefined') return 'zh-CN';\n const browserLocale = navigator.language;\n return this.normalizeLocale(browserLocale);\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n if (typeof localStorage === 'undefined') return;\n localStorage.setItem(this.storageKey, locale);\n }\n\n async loadLocale(): Promise<Locale | null> {\n if (typeof localStorage === 'undefined') return null;\n const stored = localStorage.getItem(this.storageKey);\n return stored as Locale | null;\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n 'zh-CN': 'zh-CN',\n 'zh-TW': 'zh-TW',\n 'zh-HK': 'zh-TW',\n zh: 'zh-CN',\n 'en-US': 'en-US',\n 'en-GB': 'en-US',\n en: 'en-US',\n 'ja-JP': 'ja-JP',\n ja: 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","/**\n * React Native 平台适配器\n * 用于 React Native 应用的语言检测和存储\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * React Native 平台适配器\n * 使用 AsyncStorage 存储语言偏好\n *\n * 注意:需要安装 @react-native-async-storage/async-storage\n */\nexport class ReactNativeI18nAdapter implements I18nAdapter {\n private storageKey = '@app_locale';\n\n getSystemLocale(): Locale {\n // 需要导入 react-native 的 Platform 和 NativeModules\n try {\n // @ts-ignore - react-native 在运行时动态加载\n const { Platform, NativeModules } = require('react-native');\n const locale =\n Platform.OS === 'ios'\n ? NativeModules.SettingsManager.settings.AppleLocale ||\n NativeModules.SettingsManager.settings.AppleLanguages[0]\n : NativeModules.I18nManager.localeIdentifier;\n\n return this.normalizeLocale(locale);\n } catch {\n return 'zh-CN';\n }\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n try {\n // @ts-ignore - AsyncStorage 在运行时动态加载\n const AsyncStorage = require('@react-native-async-storage/async-storage').default;\n await AsyncStorage.setItem(this.storageKey, locale);\n } catch (error) {\n console.error('Failed to save locale:', error);\n }\n }\n\n async loadLocale(): Promise<Locale | null> {\n try {\n // @ts-ignore - AsyncStorage 在运行时动态加载\n const AsyncStorage = require('@react-native-async-storage/async-storage').default;\n const stored = await AsyncStorage.getItem(this.storageKey);\n return stored as Locale | null;\n } catch (error) {\n console.error('Failed to load locale:', error);\n return null;\n }\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n 'zh-CN': 'zh-CN',\n zh_CN: 'zh-CN',\n 'zh-Hans': 'zh-CN',\n zh_Hans_CN: 'zh-CN',\n 'zh-TW': 'zh-TW',\n zh_TW: 'zh-TW',\n 'zh-Hant': 'zh-TW',\n zh_Hant_TW: 'zh-TW',\n 'en-US': 'en-US',\n en_US: 'en-US',\n en: 'en-US',\n 'ja-JP': 'ja-JP',\n ja_JP: 'ja-JP',\n ja: 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","/**\n * Taro (小程序) 平台适配器\n * 用于微信小程序、支付宝小程序等通过 Taro 开发的应用\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * Taro (小程序) 平台适配器\n * 使用 Taro.storage API 存储语言偏好\n *\n * 注意:需要安装 @tarojs/taro\n */\nexport class TaroI18nAdapter implements I18nAdapter {\n private storageKey = 'app_locale';\n\n getSystemLocale(): Locale {\n try {\n // @ts-ignore - Taro 在运行时动态加载\n const Taro = require('@tarojs/taro').default;\n const systemInfo = Taro.getSystemInfoSync();\n return this.normalizeLocale(systemInfo.language);\n } catch {\n return 'zh-CN';\n }\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n try {\n // @ts-ignore - Taro 在运行时动态加载\n const Taro = require('@tarojs/taro').default;\n await Taro.setStorage({\n key: this.storageKey,\n data: locale,\n });\n } catch (error) {\n console.error('Failed to save locale:', error);\n }\n }\n\n async loadLocale(): Promise<Locale | null> {\n try {\n // @ts-ignore - Taro 在运行时动态加载\n const Taro = require('@tarojs/taro').default;\n const res = await Taro.getStorage({\n key: this.storageKey,\n });\n return res.data as Locale | null;\n } catch (error) {\n return null;\n }\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n zh_CN: 'zh-CN',\n 'zh-CN': 'zh-CN',\n zh_TW: 'zh-TW',\n 'zh-TW': 'zh-TW',\n en: 'en-US',\n 'en-US': 'en-US',\n ja: 'ja-JP',\n 'ja-JP': 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","/**\n * Electron 平台适配器\n * 用于 Electron 桌面应用的语言检测和存储\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * Electron 平台适配器\n * 使用 localStorage 存储语言偏好\n *\n * 注意:Electron 渲染进程支持 Web API\n */\nexport class ElectronI18nAdapter implements I18nAdapter {\n private storageKey = 'app_locale';\n\n getSystemLocale(): Locale {\n if (typeof navigator === 'undefined') return 'zh-CN';\n const browserLocale = navigator.language;\n return this.normalizeLocale(browserLocale);\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n if (typeof localStorage === 'undefined') return;\n localStorage.setItem(this.storageKey, locale);\n }\n\n async loadLocale(): Promise<Locale | null> {\n if (typeof localStorage === 'undefined') return null;\n const stored = localStorage.getItem(this.storageKey);\n return stored as Locale | null;\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n 'zh-CN': 'zh-CN',\n 'zh-TW': 'zh-TW',\n 'zh-HK': 'zh-TW',\n zh: 'zh-CN',\n 'en-US': 'en-US',\n 'en-GB': 'en-US',\n en: 'en-US',\n 'ja-JP': 'ja-JP',\n ja: 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n"]}
1
+ {"version":3,"sources":["../../src/i18n/i18n.ts","../../src/i18n/hooks.ts","../../src/i18n/locales/zh-CN.ts","../../src/i18n/locales/en-US.ts","../../src/i18n/adapters/web.ts","../../src/i18n/adapters/mobile.ts","../../src/i18n/adapters/miniapp.ts","../../src/i18n/adapters/desktop.ts","../../src/i18n/components/LanguageSwitcher.tsx"],"names":["t","useState","useCallback","__require","React"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * 轻量级 i18n 核心实现\n * 支持:翻译、插值、复数、嵌套键、类型安全\n */\n\nimport type {\n Locale,\n Translations,\n LocaleResources,\n TranslateOptions,\n I18nConfig,\n I18nInstance,\n} from './types';\n\n/**\n * 默认插值函数\n * 支持 {{key}} 格式的变量替换\n */\nfunction defaultInterpolate(template: string, data: Record<string, any>): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key) => {\n return data[key]?.toString() ?? match;\n });\n}\n\n/**\n * 从嵌套对象中获取值\n * 支持 \"user.name\" 这样的路径\n */\nfunction getNestedValue(obj: any, path: string): any {\n const keys = path.split('.');\n let result = obj;\n\n for (const key of keys) {\n if (result && typeof result === 'object' && key in result) {\n result = result[key];\n } else {\n return undefined;\n }\n }\n\n return result;\n}\n\n/**\n * 创建 i18n 实例\n */\nexport function createI18n(config: I18nConfig): I18nInstance {\n let currentLocale: Locale = config.locale;\n const fallbackLocale: Locale = config.fallbackLocale || 'zh-CN';\n const resources: LocaleResources = config.resources || {};\n const interpolate = config.interpolate || defaultInterpolate;\n\n /**\n * 翻译函数\n * @param key 翻译键,支持嵌套 \"common.hello\"\n * @param options 选项\n */\n function t(key: string, options: TranslateOptions = {}): string {\n const { defaultValue, count, context = {} } = options;\n\n // 获取当前语言的翻译\n let translation = getNestedValue(resources[currentLocale], key);\n\n // 如果没有找到,尝试使用 fallback 语言\n if (translation === undefined && currentLocale !== fallbackLocale) {\n translation = getNestedValue(resources[fallbackLocale], key);\n }\n\n // 如果还是没有找到,使用默认值或键名\n if (translation === undefined) {\n return defaultValue || key;\n }\n\n // 如果不是字符串,返回 JSON 字符串\n if (typeof translation !== 'string') {\n return JSON.stringify(translation);\n }\n\n // 处理复数\n if (count !== undefined) {\n const pluralKey = count === 1 ? `${key}_one` : `${key}_other`;\n const pluralTranslation = getNestedValue(resources[currentLocale], pluralKey);\n if (pluralTranslation && typeof pluralTranslation === 'string') {\n translation = pluralTranslation;\n }\n }\n\n // 插值\n const data = { ...context, count };\n return interpolate(translation, data);\n }\n\n /**\n * 设置当前语言\n */\n function setLocale(locale: Locale): void {\n currentLocale = locale;\n }\n\n /**\n * 添加翻译资源\n */\n function addResources(locale: Locale, newResources: Translations): void {\n if (!resources[locale]) {\n resources[locale] = {};\n }\n resources[locale] = {\n ...resources[locale],\n ...newResources,\n };\n }\n\n /**\n * 获取当前语言\n */\n function getLocale(): Locale {\n return currentLocale;\n }\n\n return {\n locale: currentLocale,\n t,\n setLocale,\n addResources,\n getLocale,\n };\n}\n\n/**\n * 全局 i18n 实例(可选)\n */\nlet globalI18n: I18nInstance | null = null;\n\n/**\n * 初始化全局 i18n\n */\nexport function initI18n(config: I18nConfig): I18nInstance {\n globalI18n = createI18n(config);\n return globalI18n;\n}\n\n/**\n * 获取全局 i18n 实例\n */\nexport function getI18n(): I18nInstance {\n if (!globalI18n) {\n throw new Error('i18n not initialized. Call initI18n() first.');\n }\n return globalI18n;\n}\n\n/**\n * 快捷翻译函数\n */\nexport function t(key: string, options?: TranslateOptions): string {\n return getI18n().t(key, options);\n}\n","/**\n * React hooks for i18n\n */\n\nimport { useState, useCallback } from 'react';\nimport { getI18n } from './i18n';\nimport type { Locale, TranslateOptions } from './types';\n\n/**\n * useTranslation Hook\n * React 组件中使用翻译\n */\nexport function useTranslation() {\n const i18n = getI18n();\n const [locale, setLocaleState] = useState<Locale>(i18n.getLocale());\n\n // 翻译函数\n const t = useCallback(\n (key: string, options?: TranslateOptions): string => {\n return i18n.t(key, options);\n },\n [locale] // locale 改变时重新创建函数\n );\n\n // 切换语言\n const setLocale = useCallback((newLocale: Locale) => {\n i18n.setLocale(newLocale);\n setLocaleState(newLocale);\n }, []);\n\n return {\n t,\n locale,\n setLocale,\n };\n}\n\n/**\n * useLocale Hook\n * 只获取和设置语言,不包含翻译函数\n */\nexport function useLocale() {\n const i18n = getI18n();\n const [locale, setLocaleState] = useState<Locale>(i18n.getLocale());\n\n const setLocale = useCallback((newLocale: Locale) => {\n i18n.setLocale(newLocale);\n setLocaleState(newLocale);\n }, []);\n\n return {\n locale,\n setLocale,\n };\n}\n","/**\n * 简体中文翻译\n */\n\nexport default {\n // ==================== 应用信息 ====================\n app: {\n name: 'LyricNote',\n fullName: 'LyricNote - 歌词笔记',\n icon: '🎵',\n description: '一个强大的歌词和笔记管理应用',\n author: 'LyricNote Team',\n copyright: `© ${new Date().getFullYear()} LyricNote`,\n version: '1.0.0',\n },\n\n // ==================== 应用标题 ====================\n titles: {\n main: '🎵 LyricNote',\n admin: 'LyricNote 管理后台',\n withVersion: 'LyricNote v1.0.0',\n welcome: '欢迎使用 LyricNote',\n about: '关于 LyricNote',\n },\n\n // ==================== 通用文案 ====================\n common: {\n hello: '你好',\n welcome: '欢迎',\n confirm: '确认',\n cancel: '取消',\n save: '保存',\n delete: '删除',\n edit: '编辑',\n back: '返回',\n next: '下一步',\n submit: '提交',\n finish: '完成',\n loading: '加载中...',\n success: '操作成功',\n error: '操作失败',\n retry: '重试',\n empty: '暂无数据',\n },\n\n // ==================== 导航菜单 ====================\n nav: {\n home: '首页',\n lyrics: '歌词',\n create: '创作',\n collection: '收藏',\n profile: '我的',\n settings: '设置',\n history: '历史',\n logout: '退出登录',\n },\n\n // ==================== 用户相关 ====================\n user: {\n login: '登录',\n register: '注册',\n username: '用户名',\n password: '密码',\n email: '邮箱',\n phone: '手机号',\n nickname: '昵称',\n },\n\n // ==================== 页面标题和描述 ====================\n pages: {\n home: {\n title: '首页',\n description: '一个强大的歌词和笔记管理应用',\n },\n profile: {\n title: '个人中心',\n description: '管理您的个人信息和偏好设置',\n },\n admin: {\n title: 'LyricNote 管理后台',\n description: '系统管理和数据统计',\n },\n login: {\n title: '登录',\n description: '登录到 LyricNote',\n },\n },\n\n // ==================== 表单验证 ====================\n validation: {\n required: '{{field}}不能为空',\n invalid_email: '邮箱格式不正确',\n password_too_short: '密码至少需要{{count}}个字符',\n password_weak: '密码强度不够',\n passwords_not_match: '两次密码不一致',\n },\n\n // ==================== 状态提示 ====================\n status: {\n loading: '加载中...',\n success: '操作成功',\n error: '操作失败',\n empty: '暂无数据',\n network_error: '网络错误,请稍后重试',\n },\n\n // ==================== 错误消息 ====================\n errors: {\n network: '网络错误,请稍后重试',\n server: '服务器错误',\n unauthorized: '未授权,请先登录',\n not_found: '未找到相关内容',\n unknown: '未知错误',\n },\n\n // ==================== 成功消息 ====================\n success: {\n saved: '保存成功',\n deleted: '删除成功',\n updated: '更新成功',\n created: '创建成功',\n },\n\n // ==================== 语言设置 ====================\n language: {\n label: '语言',\n zh_cn: '简体中文',\n zh_tw: '繁體中文',\n en_us: 'English',\n ja_jp: '日本語',\n },\n} as const;\n","/**\n * English translations\n */\n\nexport default {\n // ==================== App Information ====================\n app: {\n name: 'LyricNote',\n fullName: 'LyricNote - Lyrics & Notes',\n icon: '🎵',\n description: 'A powerful lyrics and notes management app',\n author: 'LyricNote Team',\n copyright: `© ${new Date().getFullYear()} LyricNote`,\n version: '1.0.0',\n },\n\n // ==================== App Titles ====================\n titles: {\n main: '🎵 LyricNote',\n admin: 'LyricNote Admin',\n withVersion: 'LyricNote v1.0.0',\n welcome: 'Welcome to LyricNote',\n about: 'About LyricNote',\n },\n\n // ==================== Common ====================\n common: {\n hello: 'Hello',\n welcome: 'Welcome',\n confirm: 'Confirm',\n cancel: 'Cancel',\n save: 'Save',\n delete: 'Delete',\n edit: 'Edit',\n back: 'Back',\n next: 'Next',\n submit: 'Submit',\n finish: 'Finish',\n loading: 'Loading...',\n success: 'Success',\n error: 'Error',\n retry: 'Retry',\n empty: 'No data',\n },\n\n // ==================== Navigation ====================\n nav: {\n home: 'Home',\n lyrics: 'Lyrics',\n create: 'Create',\n collection: 'Collection',\n profile: 'Profile',\n settings: 'Settings',\n history: 'History',\n logout: 'Logout',\n },\n\n // ==================== User ====================\n user: {\n login: 'Login',\n register: 'Register',\n username: 'Username',\n password: 'Password',\n email: 'Email',\n phone: 'Phone',\n nickname: 'Nickname',\n },\n\n // ==================== Pages ====================\n pages: {\n home: {\n title: 'Home',\n description: 'A powerful lyrics and notes management app',\n },\n profile: {\n title: 'Profile',\n description: 'Manage your personal information and preferences',\n },\n admin: {\n title: 'LyricNote Admin',\n description: 'System management and data statistics',\n },\n login: {\n title: 'Login',\n description: 'Login to LyricNote',\n },\n },\n\n // ==================== Form Validation ====================\n validation: {\n required: '{{field}} is required',\n invalid_email: 'Invalid email format',\n password_too_short: 'Password must be at least {{count}} characters',\n password_weak: 'Password is too weak',\n passwords_not_match: 'Passwords do not match',\n },\n\n // ==================== Status Messages ====================\n status: {\n loading: 'Loading...',\n success: 'Success',\n error: 'Error',\n empty: 'No data',\n network_error: 'Network error, please try again later',\n },\n\n // ==================== Error Messages ====================\n errors: {\n network: 'Network error, please try again later',\n server: 'Server error',\n unauthorized: 'Unauthorized, please login first',\n not_found: 'Not found',\n unknown: 'Unknown error',\n },\n\n // ==================== Success Messages ====================\n success: {\n saved: 'Saved successfully',\n deleted: 'Deleted successfully',\n updated: 'Updated successfully',\n created: 'Created successfully',\n },\n\n // ==================== Language Settings ====================\n language: {\n label: 'Language',\n zh_cn: '简体中文',\n zh_tw: '繁體中文',\n en_us: 'English',\n ja_jp: '日本語',\n },\n} as const;\n","/**\n * Web 平台适配器\n * 用于浏览器环境的语言检测和存储\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * Web 平台适配器\n * 使用 localStorage 存储语言偏好\n */\nexport class WebI18nAdapter implements I18nAdapter {\n private storageKey = 'app_locale';\n\n getSystemLocale(): Locale {\n if (typeof navigator === 'undefined') return 'zh-CN';\n const browserLocale = navigator.language;\n return this.normalizeLocale(browserLocale);\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n if (typeof localStorage === 'undefined') return;\n localStorage.setItem(this.storageKey, locale);\n }\n\n async loadLocale(): Promise<Locale | null> {\n if (typeof localStorage === 'undefined') return null;\n const stored = localStorage.getItem(this.storageKey);\n return stored as Locale | null;\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n 'zh-CN': 'zh-CN',\n 'zh-TW': 'zh-TW',\n 'zh-HK': 'zh-TW',\n zh: 'zh-CN',\n 'en-US': 'en-US',\n 'en-GB': 'en-US',\n en: 'en-US',\n 'ja-JP': 'ja-JP',\n ja: 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","/**\n * React Native 平台适配器\n * 用于 React Native 应用的语言检测和存储\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * React Native 平台适配器\n * 使用 AsyncStorage 存储语言偏好\n *\n * 注意:需要安装 @react-native-async-storage/async-storage\n */\nexport class ReactNativeI18nAdapter implements I18nAdapter {\n private storageKey = '@app_locale';\n\n getSystemLocale(): Locale {\n // 需要导入 react-native 的 Platform 和 NativeModules\n try {\n // @ts-ignore - react-native 在运行时动态加载\n const { Platform, NativeModules } = require('react-native');\n const locale =\n Platform.OS === 'ios'\n ? NativeModules.SettingsManager.settings.AppleLocale ||\n NativeModules.SettingsManager.settings.AppleLanguages[0]\n : NativeModules.I18nManager.localeIdentifier;\n\n return this.normalizeLocale(locale);\n } catch {\n return 'zh-CN';\n }\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n try {\n // @ts-ignore - AsyncStorage 在运行时动态加载\n const AsyncStorage = require('@react-native-async-storage/async-storage').default;\n await AsyncStorage.setItem(this.storageKey, locale);\n } catch (error) {\n console.error('Failed to save locale:', error);\n }\n }\n\n async loadLocale(): Promise<Locale | null> {\n try {\n // @ts-ignore - AsyncStorage 在运行时动态加载\n const AsyncStorage = require('@react-native-async-storage/async-storage').default;\n const stored = await AsyncStorage.getItem(this.storageKey);\n return stored as Locale | null;\n } catch (error) {\n console.error('Failed to load locale:', error);\n return null;\n }\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n 'zh-CN': 'zh-CN',\n zh_CN: 'zh-CN',\n 'zh-Hans': 'zh-CN',\n zh_Hans_CN: 'zh-CN',\n 'zh-TW': 'zh-TW',\n zh_TW: 'zh-TW',\n 'zh-Hant': 'zh-TW',\n zh_Hant_TW: 'zh-TW',\n 'en-US': 'en-US',\n en_US: 'en-US',\n en: 'en-US',\n 'ja-JP': 'ja-JP',\n ja_JP: 'ja-JP',\n ja: 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","/**\n * Taro (小程序) 平台适配器\n * 用于微信小程序、支付宝小程序等通过 Taro 开发的应用\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * Taro (小程序) 平台适配器\n * 使用 Taro.storage API 存储语言偏好\n *\n * 注意:需要安装 @tarojs/taro\n */\nexport class TaroI18nAdapter implements I18nAdapter {\n private storageKey = 'app_locale';\n\n getSystemLocale(): Locale {\n try {\n // @ts-ignore - Taro 在运行时动态加载\n const Taro = require('@tarojs/taro').default;\n const systemInfo = Taro.getSystemInfoSync();\n return this.normalizeLocale(systemInfo.language);\n } catch {\n return 'zh-CN';\n }\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n try {\n // @ts-ignore - Taro 在运行时动态加载\n const Taro = require('@tarojs/taro').default;\n await Taro.setStorage({\n key: this.storageKey,\n data: locale,\n });\n } catch (error) {\n console.error('Failed to save locale:', error);\n }\n }\n\n async loadLocale(): Promise<Locale | null> {\n try {\n // @ts-ignore - Taro 在运行时动态加载\n const Taro = require('@tarojs/taro').default;\n const res = await Taro.getStorage({\n key: this.storageKey,\n });\n return res.data as Locale | null;\n } catch (error) {\n return null;\n }\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n zh_CN: 'zh-CN',\n 'zh-CN': 'zh-CN',\n zh_TW: 'zh-TW',\n 'zh-TW': 'zh-TW',\n en: 'en-US',\n 'en-US': 'en-US',\n ja: 'ja-JP',\n 'ja-JP': 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","/**\n * Electron 平台适配器\n * 用于 Electron 桌面应用的语言检测和存储\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * Electron 平台适配器\n * 使用 localStorage 存储语言偏好\n *\n * 注意:Electron 渲染进程支持 Web API\n */\nexport class ElectronI18nAdapter implements I18nAdapter {\n private storageKey = 'app_locale';\n\n getSystemLocale(): Locale {\n if (typeof navigator === 'undefined') return 'zh-CN';\n const browserLocale = navigator.language;\n return this.normalizeLocale(browserLocale);\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n if (typeof localStorage === 'undefined') return;\n localStorage.setItem(this.storageKey, locale);\n }\n\n async loadLocale(): Promise<Locale | null> {\n if (typeof localStorage === 'undefined') return null;\n const stored = localStorage.getItem(this.storageKey);\n return stored as Locale | null;\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n 'zh-CN': 'zh-CN',\n 'zh-TW': 'zh-TW',\n 'zh-HK': 'zh-TW',\n zh: 'zh-CN',\n 'en-US': 'en-US',\n 'en-GB': 'en-US',\n en: 'en-US',\n 'ja-JP': 'ja-JP',\n ja: 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","'use client';\n\n/**\n * 语言切换组件\n * 支持多种样式:按钮组、下拉菜单、图标按钮\n * 使用 Tailwind CSS 样式\n */\n\nimport React from 'react';\nimport { useTranslation } from '../hooks';\nimport type { Locale } from '../types';\n\n// ==================== 类型定义 ====================\n\nexport interface LanguageSwitcherProps {\n variant?: 'buttons' | 'dropdown' | 'icon';\n className?: string;\n onLanguageChange?: (locale: Locale) => void;\n}\n\nexport interface LanguageOption {\n locale: Locale;\n label: string;\n flag: string;\n}\n\n// ==================== 语言选项配置 ====================\n\nconst LANGUAGE_OPTIONS: LanguageOption[] = [\n { locale: 'zh-CN', label: '简体中文', flag: '🇨🇳' },\n { locale: 'zh-TW', label: '繁體中文', flag: '🇹🇼' },\n { locale: 'en-US', label: 'English', flag: '🇺🇸' },\n { locale: 'ja-JP', label: '日本語', flag: '🇯🇵' },\n];\n\n// ==================== 按钮组样式 ====================\n\n/**\n * 按钮组语言切换器\n */\nexport function LanguageSwitcherButtons({\n className = '',\n onLanguageChange,\n}: LanguageSwitcherProps) {\n const { locale, setLocale } = useTranslation();\n\n const handleChange = (newLocale: Locale) => {\n setLocale(newLocale);\n onLanguageChange?.(newLocale);\n };\n\n return (\n <div className={`flex gap-2 flex-wrap ${className}`}>\n {LANGUAGE_OPTIONS.map((option) => (\n <button\n key={option.locale}\n onClick={() => handleChange(option.locale)}\n className={`\n flex items-center gap-2 px-4 py-2 rounded-lg border-2\n transition-all duration-200 font-medium\n ${\n locale === option.locale\n ? 'border-blue-500 bg-blue-50 text-blue-700 shadow-md'\n : 'border-gray-300 bg-white text-gray-700 hover:border-blue-300 hover:bg-blue-50'\n }\n `}\n aria-label={option.label}\n >\n <span className=\"text-xl\">{option.flag}</span>\n <span className=\"text-sm\">{option.label}</span>\n </button>\n ))}\n </div>\n );\n}\n\n// ==================== 下拉菜单样式 ====================\n\n/**\n * 下拉菜单语言切换器\n */\nexport function LanguageSwitcherDropdown({\n className = '',\n onLanguageChange,\n}: LanguageSwitcherProps) {\n const { locale, setLocale, t } = useTranslation();\n\n const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n const newLocale = e.target.value as Locale;\n setLocale(newLocale);\n onLanguageChange?.(newLocale);\n };\n\n return (\n <div className={`flex flex-col gap-2 ${className}`}>\n <label htmlFor=\"language-select\" className=\"text-sm font-medium text-gray-700\">\n {t('language.label')}\n </label>\n <select\n id=\"language-select\"\n value={locale}\n onChange={handleChange}\n className=\"\n px-4 py-2 rounded-lg border-2 border-gray-300 bg-white\n text-gray-700 font-medium cursor-pointer\n focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500\n hover:border-gray-400 transition-colors duration-200\n \"\n aria-label={t('language.label')}\n >\n {LANGUAGE_OPTIONS.map((option) => (\n <option key={option.locale} value={option.locale}>\n {option.flag} {option.label}\n </option>\n ))}\n </select>\n </div>\n );\n}\n\n// ==================== 图标按钮样式 ====================\n\n/**\n * 图标按钮语言切换器(带下拉菜单)\n */\nexport function LanguageSwitcherIcon({ className = '', onLanguageChange }: LanguageSwitcherProps) {\n const { locale, setLocale } = useTranslation();\n const [isOpen, setIsOpen] = React.useState(false);\n\n const currentOption = LANGUAGE_OPTIONS.find((opt) => opt.locale === locale);\n\n const handleChange = (newLocale: Locale) => {\n setLocale(newLocale);\n setIsOpen(false);\n onLanguageChange?.(newLocale);\n };\n\n // 点击外部关闭下拉菜单\n React.useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n const target = event.target as HTMLElement;\n if (!target.closest('.language-switcher-icon-wrapper')) {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n return undefined;\n }, [isOpen]);\n\n return (\n <div className={`relative language-switcher-icon-wrapper ${className}`}>\n <button\n onClick={() => setIsOpen(!isOpen)}\n className=\"\n flex items-center gap-2 px-3 py-2 rounded-lg border-2 border-gray-300\n bg-white hover:border-blue-300 hover:bg-blue-50\n transition-all duration-200 cursor-pointer\n focus:outline-none focus:ring-2 focus:ring-blue-500\n \"\n aria-label=\"Switch Language\"\n aria-expanded={isOpen}\n >\n <span className=\"text-xl\">{currentOption?.flag}</span>\n <span className={`text-gray-600 text-xs transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}>\n ▼\n </span>\n </button>\n\n {isOpen && (\n <div className=\"\n absolute right-0 top-full mt-2 w-48\n bg-white border-2 border-gray-200 rounded-lg shadow-lg\n overflow-hidden z-50\n animate-in fade-in slide-in-from-top-2 duration-200\n \">\n {LANGUAGE_OPTIONS.map((option) => (\n <button\n key={option.locale}\n onClick={() => handleChange(option.locale)}\n className={`\n w-full flex items-center justify-between px-4 py-3\n transition-colors duration-150\n ${\n locale === option.locale\n ? 'bg-blue-50 text-blue-700'\n : 'text-gray-700 hover:bg-gray-50'\n }\n `}\n >\n <div className=\"flex items-center gap-3\">\n <span className=\"text-lg\">{option.flag}</span>\n <span className=\"text-sm font-medium\">{option.label}</span>\n </div>\n {locale === option.locale && (\n <span className=\"text-blue-600 font-bold\">✓</span>\n )}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// ==================== 主组件 ====================\n\n/**\n * 语言切换器主组件\n * 根据 variant 自动选择样式\n */\nexport function LanguageSwitcher({\n variant = 'buttons',\n className,\n onLanguageChange,\n}: LanguageSwitcherProps) {\n switch (variant) {\n case 'dropdown':\n return <LanguageSwitcherDropdown className={className} onLanguageChange={onLanguageChange} />;\n case 'icon':\n return <LanguageSwitcherIcon className={className} onLanguageChange={onLanguageChange} />;\n case 'buttons':\n default:\n return <LanguageSwitcherButtons className={className} onLanguageChange={onLanguageChange} />;\n }\n}\n\n// ==================== 默认导出 ====================\n\nexport default LanguageSwitcher;\n"]}
@@ -1,5 +1,5 @@
1
1
  import { __require } from '../chunk-BJTO5JO5.mjs';
2
- import { useState, useCallback } from 'react';
2
+ import React, { useState, useCallback } from 'react';
3
3
 
4
4
  // src/i18n/i18n.ts
5
5
  function defaultInterpolate(template, data) {
@@ -529,7 +529,122 @@ var ElectronI18nAdapter = class {
529
529
  return map[locale] || "zh-CN";
530
530
  }
531
531
  };
532
+ var LANGUAGE_OPTIONS = [
533
+ { locale: "zh-CN", label: "\u7B80\u4F53\u4E2D\u6587", flag: "\u{1F1E8}\u{1F1F3}" },
534
+ { locale: "zh-TW", label: "\u7E41\u9AD4\u4E2D\u6587", flag: "\u{1F1F9}\u{1F1FC}" },
535
+ { locale: "en-US", label: "English", flag: "\u{1F1FA}\u{1F1F8}" },
536
+ { locale: "ja-JP", label: "\u65E5\u672C\u8A9E", flag: "\u{1F1EF}\u{1F1F5}" }
537
+ ];
538
+ function LanguageSwitcherButtons({
539
+ className = "",
540
+ onLanguageChange
541
+ }) {
542
+ const { locale, setLocale } = useTranslation();
543
+ const handleChange = (newLocale) => {
544
+ setLocale(newLocale);
545
+ onLanguageChange?.(newLocale);
546
+ };
547
+ return /* @__PURE__ */ React.createElement("div", { className: `flex gap-2 flex-wrap ${className}` }, LANGUAGE_OPTIONS.map((option) => /* @__PURE__ */ React.createElement(
548
+ "button",
549
+ {
550
+ key: option.locale,
551
+ onClick: () => handleChange(option.locale),
552
+ className: `
553
+ flex items-center gap-2 px-4 py-2 rounded-lg border-2
554
+ transition-all duration-200 font-medium
555
+ ${locale === option.locale ? "border-blue-500 bg-blue-50 text-blue-700 shadow-md" : "border-gray-300 bg-white text-gray-700 hover:border-blue-300 hover:bg-blue-50"}
556
+ `,
557
+ "aria-label": option.label
558
+ },
559
+ /* @__PURE__ */ React.createElement("span", { className: "text-xl" }, option.flag),
560
+ /* @__PURE__ */ React.createElement("span", { className: "text-sm" }, option.label)
561
+ )));
562
+ }
563
+ function LanguageSwitcherDropdown({
564
+ className = "",
565
+ onLanguageChange
566
+ }) {
567
+ const { locale, setLocale, t: t2 } = useTranslation();
568
+ const handleChange = (e) => {
569
+ const newLocale = e.target.value;
570
+ setLocale(newLocale);
571
+ onLanguageChange?.(newLocale);
572
+ };
573
+ return /* @__PURE__ */ React.createElement("div", { className: `flex flex-col gap-2 ${className}` }, /* @__PURE__ */ React.createElement("label", { htmlFor: "language-select", className: "text-sm font-medium text-gray-700" }, t2("language.label")), /* @__PURE__ */ React.createElement(
574
+ "select",
575
+ {
576
+ id: "language-select",
577
+ value: locale,
578
+ onChange: handleChange,
579
+ className: "\n px-4 py-2 rounded-lg border-2 border-gray-300 bg-white\n text-gray-700 font-medium cursor-pointer\n focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500\n hover:border-gray-400 transition-colors duration-200\n ",
580
+ "aria-label": t2("language.label")
581
+ },
582
+ LANGUAGE_OPTIONS.map((option) => /* @__PURE__ */ React.createElement("option", { key: option.locale, value: option.locale }, option.flag, " ", option.label))
583
+ ));
584
+ }
585
+ function LanguageSwitcherIcon({ className = "", onLanguageChange }) {
586
+ const { locale, setLocale } = useTranslation();
587
+ const [isOpen, setIsOpen] = React.useState(false);
588
+ const currentOption = LANGUAGE_OPTIONS.find((opt) => opt.locale === locale);
589
+ const handleChange = (newLocale) => {
590
+ setLocale(newLocale);
591
+ setIsOpen(false);
592
+ onLanguageChange?.(newLocale);
593
+ };
594
+ React.useEffect(() => {
595
+ const handleClickOutside = (event) => {
596
+ const target = event.target;
597
+ if (!target.closest(".language-switcher-icon-wrapper")) {
598
+ setIsOpen(false);
599
+ }
600
+ };
601
+ if (isOpen) {
602
+ document.addEventListener("mousedown", handleClickOutside);
603
+ return () => document.removeEventListener("mousedown", handleClickOutside);
604
+ }
605
+ return void 0;
606
+ }, [isOpen]);
607
+ return /* @__PURE__ */ React.createElement("div", { className: `relative language-switcher-icon-wrapper ${className}` }, /* @__PURE__ */ React.createElement(
608
+ "button",
609
+ {
610
+ onClick: () => setIsOpen(!isOpen),
611
+ className: "\n flex items-center gap-2 px-3 py-2 rounded-lg border-2 border-gray-300\n bg-white hover:border-blue-300 hover:bg-blue-50\n transition-all duration-200 cursor-pointer\n focus:outline-none focus:ring-2 focus:ring-blue-500\n ",
612
+ "aria-label": "Switch Language",
613
+ "aria-expanded": isOpen
614
+ },
615
+ /* @__PURE__ */ React.createElement("span", { className: "text-xl" }, currentOption?.flag),
616
+ /* @__PURE__ */ React.createElement("span", { className: `text-gray-600 text-xs transition-transform duration-200 ${isOpen ? "rotate-180" : ""}` }, "\u25BC")
617
+ ), isOpen && /* @__PURE__ */ React.createElement("div", { className: "\n absolute right-0 top-full mt-2 w-48\n bg-white border-2 border-gray-200 rounded-lg shadow-lg\n overflow-hidden z-50\n animate-in fade-in slide-in-from-top-2 duration-200\n " }, LANGUAGE_OPTIONS.map((option) => /* @__PURE__ */ React.createElement(
618
+ "button",
619
+ {
620
+ key: option.locale,
621
+ onClick: () => handleChange(option.locale),
622
+ className: `
623
+ w-full flex items-center justify-between px-4 py-3
624
+ transition-colors duration-150
625
+ ${locale === option.locale ? "bg-blue-50 text-blue-700" : "text-gray-700 hover:bg-gray-50"}
626
+ `
627
+ },
628
+ /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React.createElement("span", { className: "text-lg" }, option.flag), /* @__PURE__ */ React.createElement("span", { className: "text-sm font-medium" }, option.label)),
629
+ locale === option.locale && /* @__PURE__ */ React.createElement("span", { className: "text-blue-600 font-bold" }, "\u2713")
630
+ ))));
631
+ }
632
+ function LanguageSwitcher({
633
+ variant = "buttons",
634
+ className,
635
+ onLanguageChange
636
+ }) {
637
+ switch (variant) {
638
+ case "dropdown":
639
+ return /* @__PURE__ */ React.createElement(LanguageSwitcherDropdown, { className, onLanguageChange });
640
+ case "icon":
641
+ return /* @__PURE__ */ React.createElement(LanguageSwitcherIcon, { className, onLanguageChange });
642
+ case "buttons":
643
+ default:
644
+ return /* @__PURE__ */ React.createElement(LanguageSwitcherButtons, { className, onLanguageChange });
645
+ }
646
+ }
532
647
 
533
- export { ElectronI18nAdapter, ReactNativeI18nAdapter, TaroI18nAdapter, WebI18nAdapter, createI18n, en_US_default as enUS, getI18n, initI18n, t, useLocale, useTranslation, zh_CN_default as zhCN };
648
+ export { ElectronI18nAdapter, LanguageSwitcher, ReactNativeI18nAdapter, TaroI18nAdapter, WebI18nAdapter, createI18n, en_US_default as enUS, getI18n, initI18n, t, useLocale, useTranslation, zh_CN_default as zhCN };
534
649
  //# sourceMappingURL=index.mjs.map
535
650
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/i18n/i18n.ts","../../src/i18n/hooks.ts","../../src/i18n/locales/zh-CN.ts","../../src/i18n/locales/en-US.ts","../../src/i18n/adapters/web.ts","../../src/i18n/adapters/mobile.ts","../../src/i18n/adapters/miniapp.ts","../../src/i18n/adapters/desktop.ts"],"names":["t"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * 轻量级 i18n 核心实现\n * 支持:翻译、插值、复数、嵌套键、类型安全\n */\n\nimport type {\n Locale,\n Translations,\n LocaleResources,\n TranslateOptions,\n I18nConfig,\n I18nInstance,\n} from './types';\n\n/**\n * 默认插值函数\n * 支持 {{key}} 格式的变量替换\n */\nfunction defaultInterpolate(template: string, data: Record<string, any>): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key) => {\n return data[key]?.toString() ?? match;\n });\n}\n\n/**\n * 从嵌套对象中获取值\n * 支持 \"user.name\" 这样的路径\n */\nfunction getNestedValue(obj: any, path: string): any {\n const keys = path.split('.');\n let result = obj;\n\n for (const key of keys) {\n if (result && typeof result === 'object' && key in result) {\n result = result[key];\n } else {\n return undefined;\n }\n }\n\n return result;\n}\n\n/**\n * 创建 i18n 实例\n */\nexport function createI18n(config: I18nConfig): I18nInstance {\n let currentLocale: Locale = config.locale;\n const fallbackLocale: Locale = config.fallbackLocale || 'zh-CN';\n const resources: LocaleResources = config.resources || {};\n const interpolate = config.interpolate || defaultInterpolate;\n\n /**\n * 翻译函数\n * @param key 翻译键,支持嵌套 \"common.hello\"\n * @param options 选项\n */\n function t(key: string, options: TranslateOptions = {}): string {\n const { defaultValue, count, context = {} } = options;\n\n // 获取当前语言的翻译\n let translation = getNestedValue(resources[currentLocale], key);\n\n // 如果没有找到,尝试使用 fallback 语言\n if (translation === undefined && currentLocale !== fallbackLocale) {\n translation = getNestedValue(resources[fallbackLocale], key);\n }\n\n // 如果还是没有找到,使用默认值或键名\n if (translation === undefined) {\n return defaultValue || key;\n }\n\n // 如果不是字符串,返回 JSON 字符串\n if (typeof translation !== 'string') {\n return JSON.stringify(translation);\n }\n\n // 处理复数\n if (count !== undefined) {\n const pluralKey = count === 1 ? `${key}_one` : `${key}_other`;\n const pluralTranslation = getNestedValue(resources[currentLocale], pluralKey);\n if (pluralTranslation && typeof pluralTranslation === 'string') {\n translation = pluralTranslation;\n }\n }\n\n // 插值\n const data = { ...context, count };\n return interpolate(translation, data);\n }\n\n /**\n * 设置当前语言\n */\n function setLocale(locale: Locale): void {\n currentLocale = locale;\n }\n\n /**\n * 添加翻译资源\n */\n function addResources(locale: Locale, newResources: Translations): void {\n if (!resources[locale]) {\n resources[locale] = {};\n }\n resources[locale] = {\n ...resources[locale],\n ...newResources,\n };\n }\n\n /**\n * 获取当前语言\n */\n function getLocale(): Locale {\n return currentLocale;\n }\n\n return {\n locale: currentLocale,\n t,\n setLocale,\n addResources,\n getLocale,\n };\n}\n\n/**\n * 全局 i18n 实例(可选)\n */\nlet globalI18n: I18nInstance | null = null;\n\n/**\n * 初始化全局 i18n\n */\nexport function initI18n(config: I18nConfig): I18nInstance {\n globalI18n = createI18n(config);\n return globalI18n;\n}\n\n/**\n * 获取全局 i18n 实例\n */\nexport function getI18n(): I18nInstance {\n if (!globalI18n) {\n throw new Error('i18n not initialized. Call initI18n() first.');\n }\n return globalI18n;\n}\n\n/**\n * 快捷翻译函数\n */\nexport function t(key: string, options?: TranslateOptions): string {\n return getI18n().t(key, options);\n}\n","/**\n * React hooks for i18n\n */\n\nimport { useState, useCallback } from 'react';\nimport { getI18n } from './i18n';\nimport type { Locale, TranslateOptions } from './types';\n\n/**\n * useTranslation Hook\n * React 组件中使用翻译\n */\nexport function useTranslation() {\n const i18n = getI18n();\n const [locale, setLocaleState] = useState<Locale>(i18n.getLocale());\n\n // 翻译函数\n const t = useCallback(\n (key: string, options?: TranslateOptions): string => {\n return i18n.t(key, options);\n },\n [locale] // locale 改变时重新创建函数\n );\n\n // 切换语言\n const setLocale = useCallback((newLocale: Locale) => {\n i18n.setLocale(newLocale);\n setLocaleState(newLocale);\n }, []);\n\n return {\n t,\n locale,\n setLocale,\n };\n}\n\n/**\n * useLocale Hook\n * 只获取和设置语言,不包含翻译函数\n */\nexport function useLocale() {\n const i18n = getI18n();\n const [locale, setLocaleState] = useState<Locale>(i18n.getLocale());\n\n const setLocale = useCallback((newLocale: Locale) => {\n i18n.setLocale(newLocale);\n setLocaleState(newLocale);\n }, []);\n\n return {\n locale,\n setLocale,\n };\n}\n","/**\n * 简体中文翻译\n */\n\nexport default {\n // ==================== 应用信息 ====================\n app: {\n name: 'LyricNote',\n fullName: 'LyricNote - 歌词笔记',\n icon: '🎵',\n description: '一个强大的歌词和笔记管理应用',\n author: 'LyricNote Team',\n copyright: `© ${new Date().getFullYear()} LyricNote`,\n version: '1.0.0',\n },\n\n // ==================== 应用标题 ====================\n titles: {\n main: '🎵 LyricNote',\n admin: 'LyricNote 管理后台',\n withVersion: 'LyricNote v1.0.0',\n welcome: '欢迎使用 LyricNote',\n about: '关于 LyricNote',\n },\n\n // ==================== 通用文案 ====================\n common: {\n hello: '你好',\n welcome: '欢迎',\n confirm: '确认',\n cancel: '取消',\n save: '保存',\n delete: '删除',\n edit: '编辑',\n back: '返回',\n next: '下一步',\n submit: '提交',\n finish: '完成',\n loading: '加载中...',\n success: '操作成功',\n error: '操作失败',\n retry: '重试',\n empty: '暂无数据',\n },\n\n // ==================== 导航菜单 ====================\n nav: {\n home: '首页',\n lyrics: '歌词',\n create: '创作',\n collection: '收藏',\n profile: '我的',\n settings: '设置',\n history: '历史',\n logout: '退出登录',\n },\n\n // ==================== 用户相关 ====================\n user: {\n login: '登录',\n register: '注册',\n username: '用户名',\n password: '密码',\n email: '邮箱',\n phone: '手机号',\n nickname: '昵称',\n },\n\n // ==================== 页面标题和描述 ====================\n pages: {\n home: {\n title: '首页',\n description: '一个强大的歌词和笔记管理应用',\n },\n profile: {\n title: '个人中心',\n description: '管理您的个人信息和偏好设置',\n },\n admin: {\n title: 'LyricNote 管理后台',\n description: '系统管理和数据统计',\n },\n login: {\n title: '登录',\n description: '登录到 LyricNote',\n },\n },\n\n // ==================== 表单验证 ====================\n validation: {\n required: '{{field}}不能为空',\n invalid_email: '邮箱格式不正确',\n password_too_short: '密码至少需要{{count}}个字符',\n password_weak: '密码强度不够',\n passwords_not_match: '两次密码不一致',\n },\n\n // ==================== 状态提示 ====================\n status: {\n loading: '加载中...',\n success: '操作成功',\n error: '操作失败',\n empty: '暂无数据',\n network_error: '网络错误,请稍后重试',\n },\n\n // ==================== 错误消息 ====================\n errors: {\n network: '网络错误,请稍后重试',\n server: '服务器错误',\n unauthorized: '未授权,请先登录',\n not_found: '未找到相关内容',\n unknown: '未知错误',\n },\n\n // ==================== 成功消息 ====================\n success: {\n saved: '保存成功',\n deleted: '删除成功',\n updated: '更新成功',\n created: '创建成功',\n },\n\n // ==================== 语言设置 ====================\n language: {\n label: '语言',\n zh_cn: '简体中文',\n zh_tw: '繁體中文',\n en_us: 'English',\n ja_jp: '日本語',\n },\n} as const;\n","/**\n * English translations\n */\n\nexport default {\n // ==================== App Information ====================\n app: {\n name: 'LyricNote',\n fullName: 'LyricNote - Lyrics & Notes',\n icon: '🎵',\n description: 'A powerful lyrics and notes management app',\n author: 'LyricNote Team',\n copyright: `© ${new Date().getFullYear()} LyricNote`,\n version: '1.0.0',\n },\n\n // ==================== App Titles ====================\n titles: {\n main: '🎵 LyricNote',\n admin: 'LyricNote Admin',\n withVersion: 'LyricNote v1.0.0',\n welcome: 'Welcome to LyricNote',\n about: 'About LyricNote',\n },\n\n // ==================== Common ====================\n common: {\n hello: 'Hello',\n welcome: 'Welcome',\n confirm: 'Confirm',\n cancel: 'Cancel',\n save: 'Save',\n delete: 'Delete',\n edit: 'Edit',\n back: 'Back',\n next: 'Next',\n submit: 'Submit',\n finish: 'Finish',\n loading: 'Loading...',\n success: 'Success',\n error: 'Error',\n retry: 'Retry',\n empty: 'No data',\n },\n\n // ==================== Navigation ====================\n nav: {\n home: 'Home',\n lyrics: 'Lyrics',\n create: 'Create',\n collection: 'Collection',\n profile: 'Profile',\n settings: 'Settings',\n history: 'History',\n logout: 'Logout',\n },\n\n // ==================== User ====================\n user: {\n login: 'Login',\n register: 'Register',\n username: 'Username',\n password: 'Password',\n email: 'Email',\n phone: 'Phone',\n nickname: 'Nickname',\n },\n\n // ==================== Pages ====================\n pages: {\n home: {\n title: 'Home',\n description: 'A powerful lyrics and notes management app',\n },\n profile: {\n title: 'Profile',\n description: 'Manage your personal information and preferences',\n },\n admin: {\n title: 'LyricNote Admin',\n description: 'System management and data statistics',\n },\n login: {\n title: 'Login',\n description: 'Login to LyricNote',\n },\n },\n\n // ==================== Form Validation ====================\n validation: {\n required: '{{field}} is required',\n invalid_email: 'Invalid email format',\n password_too_short: 'Password must be at least {{count}} characters',\n password_weak: 'Password is too weak',\n passwords_not_match: 'Passwords do not match',\n },\n\n // ==================== Status Messages ====================\n status: {\n loading: 'Loading...',\n success: 'Success',\n error: 'Error',\n empty: 'No data',\n network_error: 'Network error, please try again later',\n },\n\n // ==================== Error Messages ====================\n errors: {\n network: 'Network error, please try again later',\n server: 'Server error',\n unauthorized: 'Unauthorized, please login first',\n not_found: 'Not found',\n unknown: 'Unknown error',\n },\n\n // ==================== Success Messages ====================\n success: {\n saved: 'Saved successfully',\n deleted: 'Deleted successfully',\n updated: 'Updated successfully',\n created: 'Created successfully',\n },\n\n // ==================== Language Settings ====================\n language: {\n label: 'Language',\n zh_cn: '简体中文',\n zh_tw: '繁體中文',\n en_us: 'English',\n ja_jp: '日本語',\n },\n} as const;\n","/**\n * Web 平台适配器\n * 用于浏览器环境的语言检测和存储\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * Web 平台适配器\n * 使用 localStorage 存储语言偏好\n */\nexport class WebI18nAdapter implements I18nAdapter {\n private storageKey = 'app_locale';\n\n getSystemLocale(): Locale {\n if (typeof navigator === 'undefined') return 'zh-CN';\n const browserLocale = navigator.language;\n return this.normalizeLocale(browserLocale);\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n if (typeof localStorage === 'undefined') return;\n localStorage.setItem(this.storageKey, locale);\n }\n\n async loadLocale(): Promise<Locale | null> {\n if (typeof localStorage === 'undefined') return null;\n const stored = localStorage.getItem(this.storageKey);\n return stored as Locale | null;\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n 'zh-CN': 'zh-CN',\n 'zh-TW': 'zh-TW',\n 'zh-HK': 'zh-TW',\n zh: 'zh-CN',\n 'en-US': 'en-US',\n 'en-GB': 'en-US',\n en: 'en-US',\n 'ja-JP': 'ja-JP',\n ja: 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","/**\n * React Native 平台适配器\n * 用于 React Native 应用的语言检测和存储\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * React Native 平台适配器\n * 使用 AsyncStorage 存储语言偏好\n *\n * 注意:需要安装 @react-native-async-storage/async-storage\n */\nexport class ReactNativeI18nAdapter implements I18nAdapter {\n private storageKey = '@app_locale';\n\n getSystemLocale(): Locale {\n // 需要导入 react-native 的 Platform 和 NativeModules\n try {\n // @ts-ignore - react-native 在运行时动态加载\n const { Platform, NativeModules } = require('react-native');\n const locale =\n Platform.OS === 'ios'\n ? NativeModules.SettingsManager.settings.AppleLocale ||\n NativeModules.SettingsManager.settings.AppleLanguages[0]\n : NativeModules.I18nManager.localeIdentifier;\n\n return this.normalizeLocale(locale);\n } catch {\n return 'zh-CN';\n }\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n try {\n // @ts-ignore - AsyncStorage 在运行时动态加载\n const AsyncStorage = require('@react-native-async-storage/async-storage').default;\n await AsyncStorage.setItem(this.storageKey, locale);\n } catch (error) {\n console.error('Failed to save locale:', error);\n }\n }\n\n async loadLocale(): Promise<Locale | null> {\n try {\n // @ts-ignore - AsyncStorage 在运行时动态加载\n const AsyncStorage = require('@react-native-async-storage/async-storage').default;\n const stored = await AsyncStorage.getItem(this.storageKey);\n return stored as Locale | null;\n } catch (error) {\n console.error('Failed to load locale:', error);\n return null;\n }\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n 'zh-CN': 'zh-CN',\n zh_CN: 'zh-CN',\n 'zh-Hans': 'zh-CN',\n zh_Hans_CN: 'zh-CN',\n 'zh-TW': 'zh-TW',\n zh_TW: 'zh-TW',\n 'zh-Hant': 'zh-TW',\n zh_Hant_TW: 'zh-TW',\n 'en-US': 'en-US',\n en_US: 'en-US',\n en: 'en-US',\n 'ja-JP': 'ja-JP',\n ja_JP: 'ja-JP',\n ja: 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","/**\n * Taro (小程序) 平台适配器\n * 用于微信小程序、支付宝小程序等通过 Taro 开发的应用\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * Taro (小程序) 平台适配器\n * 使用 Taro.storage API 存储语言偏好\n *\n * 注意:需要安装 @tarojs/taro\n */\nexport class TaroI18nAdapter implements I18nAdapter {\n private storageKey = 'app_locale';\n\n getSystemLocale(): Locale {\n try {\n // @ts-ignore - Taro 在运行时动态加载\n const Taro = require('@tarojs/taro').default;\n const systemInfo = Taro.getSystemInfoSync();\n return this.normalizeLocale(systemInfo.language);\n } catch {\n return 'zh-CN';\n }\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n try {\n // @ts-ignore - Taro 在运行时动态加载\n const Taro = require('@tarojs/taro').default;\n await Taro.setStorage({\n key: this.storageKey,\n data: locale,\n });\n } catch (error) {\n console.error('Failed to save locale:', error);\n }\n }\n\n async loadLocale(): Promise<Locale | null> {\n try {\n // @ts-ignore - Taro 在运行时动态加载\n const Taro = require('@tarojs/taro').default;\n const res = await Taro.getStorage({\n key: this.storageKey,\n });\n return res.data as Locale | null;\n } catch (error) {\n return null;\n }\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n zh_CN: 'zh-CN',\n 'zh-CN': 'zh-CN',\n zh_TW: 'zh-TW',\n 'zh-TW': 'zh-TW',\n en: 'en-US',\n 'en-US': 'en-US',\n ja: 'ja-JP',\n 'ja-JP': 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","/**\n * Electron 平台适配器\n * 用于 Electron 桌面应用的语言检测和存储\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * Electron 平台适配器\n * 使用 localStorage 存储语言偏好\n *\n * 注意:Electron 渲染进程支持 Web API\n */\nexport class ElectronI18nAdapter implements I18nAdapter {\n private storageKey = 'app_locale';\n\n getSystemLocale(): Locale {\n if (typeof navigator === 'undefined') return 'zh-CN';\n const browserLocale = navigator.language;\n return this.normalizeLocale(browserLocale);\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n if (typeof localStorage === 'undefined') return;\n localStorage.setItem(this.storageKey, locale);\n }\n\n async loadLocale(): Promise<Locale | null> {\n if (typeof localStorage === 'undefined') return null;\n const stored = localStorage.getItem(this.storageKey);\n return stored as Locale | null;\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n 'zh-CN': 'zh-CN',\n 'zh-TW': 'zh-TW',\n 'zh-HK': 'zh-TW',\n zh: 'zh-CN',\n 'en-US': 'en-US',\n 'en-GB': 'en-US',\n en: 'en-US',\n 'ja-JP': 'ja-JP',\n ja: 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n"]}
1
+ {"version":3,"sources":["../../src/i18n/i18n.ts","../../src/i18n/hooks.ts","../../src/i18n/locales/zh-CN.ts","../../src/i18n/locales/en-US.ts","../../src/i18n/adapters/web.ts","../../src/i18n/adapters/mobile.ts","../../src/i18n/adapters/miniapp.ts","../../src/i18n/adapters/desktop.ts","../../src/i18n/components/LanguageSwitcher.tsx"],"names":["t"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * 轻量级 i18n 核心实现\n * 支持:翻译、插值、复数、嵌套键、类型安全\n */\n\nimport type {\n Locale,\n Translations,\n LocaleResources,\n TranslateOptions,\n I18nConfig,\n I18nInstance,\n} from './types';\n\n/**\n * 默认插值函数\n * 支持 {{key}} 格式的变量替换\n */\nfunction defaultInterpolate(template: string, data: Record<string, any>): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key) => {\n return data[key]?.toString() ?? match;\n });\n}\n\n/**\n * 从嵌套对象中获取值\n * 支持 \"user.name\" 这样的路径\n */\nfunction getNestedValue(obj: any, path: string): any {\n const keys = path.split('.');\n let result = obj;\n\n for (const key of keys) {\n if (result && typeof result === 'object' && key in result) {\n result = result[key];\n } else {\n return undefined;\n }\n }\n\n return result;\n}\n\n/**\n * 创建 i18n 实例\n */\nexport function createI18n(config: I18nConfig): I18nInstance {\n let currentLocale: Locale = config.locale;\n const fallbackLocale: Locale = config.fallbackLocale || 'zh-CN';\n const resources: LocaleResources = config.resources || {};\n const interpolate = config.interpolate || defaultInterpolate;\n\n /**\n * 翻译函数\n * @param key 翻译键,支持嵌套 \"common.hello\"\n * @param options 选项\n */\n function t(key: string, options: TranslateOptions = {}): string {\n const { defaultValue, count, context = {} } = options;\n\n // 获取当前语言的翻译\n let translation = getNestedValue(resources[currentLocale], key);\n\n // 如果没有找到,尝试使用 fallback 语言\n if (translation === undefined && currentLocale !== fallbackLocale) {\n translation = getNestedValue(resources[fallbackLocale], key);\n }\n\n // 如果还是没有找到,使用默认值或键名\n if (translation === undefined) {\n return defaultValue || key;\n }\n\n // 如果不是字符串,返回 JSON 字符串\n if (typeof translation !== 'string') {\n return JSON.stringify(translation);\n }\n\n // 处理复数\n if (count !== undefined) {\n const pluralKey = count === 1 ? `${key}_one` : `${key}_other`;\n const pluralTranslation = getNestedValue(resources[currentLocale], pluralKey);\n if (pluralTranslation && typeof pluralTranslation === 'string') {\n translation = pluralTranslation;\n }\n }\n\n // 插值\n const data = { ...context, count };\n return interpolate(translation, data);\n }\n\n /**\n * 设置当前语言\n */\n function setLocale(locale: Locale): void {\n currentLocale = locale;\n }\n\n /**\n * 添加翻译资源\n */\n function addResources(locale: Locale, newResources: Translations): void {\n if (!resources[locale]) {\n resources[locale] = {};\n }\n resources[locale] = {\n ...resources[locale],\n ...newResources,\n };\n }\n\n /**\n * 获取当前语言\n */\n function getLocale(): Locale {\n return currentLocale;\n }\n\n return {\n locale: currentLocale,\n t,\n setLocale,\n addResources,\n getLocale,\n };\n}\n\n/**\n * 全局 i18n 实例(可选)\n */\nlet globalI18n: I18nInstance | null = null;\n\n/**\n * 初始化全局 i18n\n */\nexport function initI18n(config: I18nConfig): I18nInstance {\n globalI18n = createI18n(config);\n return globalI18n;\n}\n\n/**\n * 获取全局 i18n 实例\n */\nexport function getI18n(): I18nInstance {\n if (!globalI18n) {\n throw new Error('i18n not initialized. Call initI18n() first.');\n }\n return globalI18n;\n}\n\n/**\n * 快捷翻译函数\n */\nexport function t(key: string, options?: TranslateOptions): string {\n return getI18n().t(key, options);\n}\n","/**\n * React hooks for i18n\n */\n\nimport { useState, useCallback } from 'react';\nimport { getI18n } from './i18n';\nimport type { Locale, TranslateOptions } from './types';\n\n/**\n * useTranslation Hook\n * React 组件中使用翻译\n */\nexport function useTranslation() {\n const i18n = getI18n();\n const [locale, setLocaleState] = useState<Locale>(i18n.getLocale());\n\n // 翻译函数\n const t = useCallback(\n (key: string, options?: TranslateOptions): string => {\n return i18n.t(key, options);\n },\n [locale] // locale 改变时重新创建函数\n );\n\n // 切换语言\n const setLocale = useCallback((newLocale: Locale) => {\n i18n.setLocale(newLocale);\n setLocaleState(newLocale);\n }, []);\n\n return {\n t,\n locale,\n setLocale,\n };\n}\n\n/**\n * useLocale Hook\n * 只获取和设置语言,不包含翻译函数\n */\nexport function useLocale() {\n const i18n = getI18n();\n const [locale, setLocaleState] = useState<Locale>(i18n.getLocale());\n\n const setLocale = useCallback((newLocale: Locale) => {\n i18n.setLocale(newLocale);\n setLocaleState(newLocale);\n }, []);\n\n return {\n locale,\n setLocale,\n };\n}\n","/**\n * 简体中文翻译\n */\n\nexport default {\n // ==================== 应用信息 ====================\n app: {\n name: 'LyricNote',\n fullName: 'LyricNote - 歌词笔记',\n icon: '🎵',\n description: '一个强大的歌词和笔记管理应用',\n author: 'LyricNote Team',\n copyright: `© ${new Date().getFullYear()} LyricNote`,\n version: '1.0.0',\n },\n\n // ==================== 应用标题 ====================\n titles: {\n main: '🎵 LyricNote',\n admin: 'LyricNote 管理后台',\n withVersion: 'LyricNote v1.0.0',\n welcome: '欢迎使用 LyricNote',\n about: '关于 LyricNote',\n },\n\n // ==================== 通用文案 ====================\n common: {\n hello: '你好',\n welcome: '欢迎',\n confirm: '确认',\n cancel: '取消',\n save: '保存',\n delete: '删除',\n edit: '编辑',\n back: '返回',\n next: '下一步',\n submit: '提交',\n finish: '完成',\n loading: '加载中...',\n success: '操作成功',\n error: '操作失败',\n retry: '重试',\n empty: '暂无数据',\n },\n\n // ==================== 导航菜单 ====================\n nav: {\n home: '首页',\n lyrics: '歌词',\n create: '创作',\n collection: '收藏',\n profile: '我的',\n settings: '设置',\n history: '历史',\n logout: '退出登录',\n },\n\n // ==================== 用户相关 ====================\n user: {\n login: '登录',\n register: '注册',\n username: '用户名',\n password: '密码',\n email: '邮箱',\n phone: '手机号',\n nickname: '昵称',\n },\n\n // ==================== 页面标题和描述 ====================\n pages: {\n home: {\n title: '首页',\n description: '一个强大的歌词和笔记管理应用',\n },\n profile: {\n title: '个人中心',\n description: '管理您的个人信息和偏好设置',\n },\n admin: {\n title: 'LyricNote 管理后台',\n description: '系统管理和数据统计',\n },\n login: {\n title: '登录',\n description: '登录到 LyricNote',\n },\n },\n\n // ==================== 表单验证 ====================\n validation: {\n required: '{{field}}不能为空',\n invalid_email: '邮箱格式不正确',\n password_too_short: '密码至少需要{{count}}个字符',\n password_weak: '密码强度不够',\n passwords_not_match: '两次密码不一致',\n },\n\n // ==================== 状态提示 ====================\n status: {\n loading: '加载中...',\n success: '操作成功',\n error: '操作失败',\n empty: '暂无数据',\n network_error: '网络错误,请稍后重试',\n },\n\n // ==================== 错误消息 ====================\n errors: {\n network: '网络错误,请稍后重试',\n server: '服务器错误',\n unauthorized: '未授权,请先登录',\n not_found: '未找到相关内容',\n unknown: '未知错误',\n },\n\n // ==================== 成功消息 ====================\n success: {\n saved: '保存成功',\n deleted: '删除成功',\n updated: '更新成功',\n created: '创建成功',\n },\n\n // ==================== 语言设置 ====================\n language: {\n label: '语言',\n zh_cn: '简体中文',\n zh_tw: '繁體中文',\n en_us: 'English',\n ja_jp: '日本語',\n },\n} as const;\n","/**\n * English translations\n */\n\nexport default {\n // ==================== App Information ====================\n app: {\n name: 'LyricNote',\n fullName: 'LyricNote - Lyrics & Notes',\n icon: '🎵',\n description: 'A powerful lyrics and notes management app',\n author: 'LyricNote Team',\n copyright: `© ${new Date().getFullYear()} LyricNote`,\n version: '1.0.0',\n },\n\n // ==================== App Titles ====================\n titles: {\n main: '🎵 LyricNote',\n admin: 'LyricNote Admin',\n withVersion: 'LyricNote v1.0.0',\n welcome: 'Welcome to LyricNote',\n about: 'About LyricNote',\n },\n\n // ==================== Common ====================\n common: {\n hello: 'Hello',\n welcome: 'Welcome',\n confirm: 'Confirm',\n cancel: 'Cancel',\n save: 'Save',\n delete: 'Delete',\n edit: 'Edit',\n back: 'Back',\n next: 'Next',\n submit: 'Submit',\n finish: 'Finish',\n loading: 'Loading...',\n success: 'Success',\n error: 'Error',\n retry: 'Retry',\n empty: 'No data',\n },\n\n // ==================== Navigation ====================\n nav: {\n home: 'Home',\n lyrics: 'Lyrics',\n create: 'Create',\n collection: 'Collection',\n profile: 'Profile',\n settings: 'Settings',\n history: 'History',\n logout: 'Logout',\n },\n\n // ==================== User ====================\n user: {\n login: 'Login',\n register: 'Register',\n username: 'Username',\n password: 'Password',\n email: 'Email',\n phone: 'Phone',\n nickname: 'Nickname',\n },\n\n // ==================== Pages ====================\n pages: {\n home: {\n title: 'Home',\n description: 'A powerful lyrics and notes management app',\n },\n profile: {\n title: 'Profile',\n description: 'Manage your personal information and preferences',\n },\n admin: {\n title: 'LyricNote Admin',\n description: 'System management and data statistics',\n },\n login: {\n title: 'Login',\n description: 'Login to LyricNote',\n },\n },\n\n // ==================== Form Validation ====================\n validation: {\n required: '{{field}} is required',\n invalid_email: 'Invalid email format',\n password_too_short: 'Password must be at least {{count}} characters',\n password_weak: 'Password is too weak',\n passwords_not_match: 'Passwords do not match',\n },\n\n // ==================== Status Messages ====================\n status: {\n loading: 'Loading...',\n success: 'Success',\n error: 'Error',\n empty: 'No data',\n network_error: 'Network error, please try again later',\n },\n\n // ==================== Error Messages ====================\n errors: {\n network: 'Network error, please try again later',\n server: 'Server error',\n unauthorized: 'Unauthorized, please login first',\n not_found: 'Not found',\n unknown: 'Unknown error',\n },\n\n // ==================== Success Messages ====================\n success: {\n saved: 'Saved successfully',\n deleted: 'Deleted successfully',\n updated: 'Updated successfully',\n created: 'Created successfully',\n },\n\n // ==================== Language Settings ====================\n language: {\n label: 'Language',\n zh_cn: '简体中文',\n zh_tw: '繁體中文',\n en_us: 'English',\n ja_jp: '日本語',\n },\n} as const;\n","/**\n * Web 平台适配器\n * 用于浏览器环境的语言检测和存储\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * Web 平台适配器\n * 使用 localStorage 存储语言偏好\n */\nexport class WebI18nAdapter implements I18nAdapter {\n private storageKey = 'app_locale';\n\n getSystemLocale(): Locale {\n if (typeof navigator === 'undefined') return 'zh-CN';\n const browserLocale = navigator.language;\n return this.normalizeLocale(browserLocale);\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n if (typeof localStorage === 'undefined') return;\n localStorage.setItem(this.storageKey, locale);\n }\n\n async loadLocale(): Promise<Locale | null> {\n if (typeof localStorage === 'undefined') return null;\n const stored = localStorage.getItem(this.storageKey);\n return stored as Locale | null;\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n 'zh-CN': 'zh-CN',\n 'zh-TW': 'zh-TW',\n 'zh-HK': 'zh-TW',\n zh: 'zh-CN',\n 'en-US': 'en-US',\n 'en-GB': 'en-US',\n en: 'en-US',\n 'ja-JP': 'ja-JP',\n ja: 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","/**\n * React Native 平台适配器\n * 用于 React Native 应用的语言检测和存储\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * React Native 平台适配器\n * 使用 AsyncStorage 存储语言偏好\n *\n * 注意:需要安装 @react-native-async-storage/async-storage\n */\nexport class ReactNativeI18nAdapter implements I18nAdapter {\n private storageKey = '@app_locale';\n\n getSystemLocale(): Locale {\n // 需要导入 react-native 的 Platform 和 NativeModules\n try {\n // @ts-ignore - react-native 在运行时动态加载\n const { Platform, NativeModules } = require('react-native');\n const locale =\n Platform.OS === 'ios'\n ? NativeModules.SettingsManager.settings.AppleLocale ||\n NativeModules.SettingsManager.settings.AppleLanguages[0]\n : NativeModules.I18nManager.localeIdentifier;\n\n return this.normalizeLocale(locale);\n } catch {\n return 'zh-CN';\n }\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n try {\n // @ts-ignore - AsyncStorage 在运行时动态加载\n const AsyncStorage = require('@react-native-async-storage/async-storage').default;\n await AsyncStorage.setItem(this.storageKey, locale);\n } catch (error) {\n console.error('Failed to save locale:', error);\n }\n }\n\n async loadLocale(): Promise<Locale | null> {\n try {\n // @ts-ignore - AsyncStorage 在运行时动态加载\n const AsyncStorage = require('@react-native-async-storage/async-storage').default;\n const stored = await AsyncStorage.getItem(this.storageKey);\n return stored as Locale | null;\n } catch (error) {\n console.error('Failed to load locale:', error);\n return null;\n }\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n 'zh-CN': 'zh-CN',\n zh_CN: 'zh-CN',\n 'zh-Hans': 'zh-CN',\n zh_Hans_CN: 'zh-CN',\n 'zh-TW': 'zh-TW',\n zh_TW: 'zh-TW',\n 'zh-Hant': 'zh-TW',\n zh_Hant_TW: 'zh-TW',\n 'en-US': 'en-US',\n en_US: 'en-US',\n en: 'en-US',\n 'ja-JP': 'ja-JP',\n ja_JP: 'ja-JP',\n ja: 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","/**\n * Taro (小程序) 平台适配器\n * 用于微信小程序、支付宝小程序等通过 Taro 开发的应用\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * Taro (小程序) 平台适配器\n * 使用 Taro.storage API 存储语言偏好\n *\n * 注意:需要安装 @tarojs/taro\n */\nexport class TaroI18nAdapter implements I18nAdapter {\n private storageKey = 'app_locale';\n\n getSystemLocale(): Locale {\n try {\n // @ts-ignore - Taro 在运行时动态加载\n const Taro = require('@tarojs/taro').default;\n const systemInfo = Taro.getSystemInfoSync();\n return this.normalizeLocale(systemInfo.language);\n } catch {\n return 'zh-CN';\n }\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n try {\n // @ts-ignore - Taro 在运行时动态加载\n const Taro = require('@tarojs/taro').default;\n await Taro.setStorage({\n key: this.storageKey,\n data: locale,\n });\n } catch (error) {\n console.error('Failed to save locale:', error);\n }\n }\n\n async loadLocale(): Promise<Locale | null> {\n try {\n // @ts-ignore - Taro 在运行时动态加载\n const Taro = require('@tarojs/taro').default;\n const res = await Taro.getStorage({\n key: this.storageKey,\n });\n return res.data as Locale | null;\n } catch (error) {\n return null;\n }\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n zh_CN: 'zh-CN',\n 'zh-CN': 'zh-CN',\n zh_TW: 'zh-TW',\n 'zh-TW': 'zh-TW',\n en: 'en-US',\n 'en-US': 'en-US',\n ja: 'ja-JP',\n 'ja-JP': 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","/**\n * Electron 平台适配器\n * 用于 Electron 桌面应用的语言检测和存储\n */\n\nimport type { Locale, I18nAdapter } from '../types';\n\n/**\n * Electron 平台适配器\n * 使用 localStorage 存储语言偏好\n *\n * 注意:Electron 渲染进程支持 Web API\n */\nexport class ElectronI18nAdapter implements I18nAdapter {\n private storageKey = 'app_locale';\n\n getSystemLocale(): Locale {\n if (typeof navigator === 'undefined') return 'zh-CN';\n const browserLocale = navigator.language;\n return this.normalizeLocale(browserLocale);\n }\n\n async saveLocale(locale: Locale): Promise<void> {\n if (typeof localStorage === 'undefined') return;\n localStorage.setItem(this.storageKey, locale);\n }\n\n async loadLocale(): Promise<Locale | null> {\n if (typeof localStorage === 'undefined') return null;\n const stored = localStorage.getItem(this.storageKey);\n return stored as Locale | null;\n }\n\n private normalizeLocale(locale: string): Locale {\n const map: Record<string, Locale> = {\n 'zh-CN': 'zh-CN',\n 'zh-TW': 'zh-TW',\n 'zh-HK': 'zh-TW',\n zh: 'zh-CN',\n 'en-US': 'en-US',\n 'en-GB': 'en-US',\n en: 'en-US',\n 'ja-JP': 'ja-JP',\n ja: 'ja-JP',\n };\n return map[locale] || 'zh-CN';\n }\n}\n\n","'use client';\n\n/**\n * 语言切换组件\n * 支持多种样式:按钮组、下拉菜单、图标按钮\n * 使用 Tailwind CSS 样式\n */\n\nimport React from 'react';\nimport { useTranslation } from '../hooks';\nimport type { Locale } from '../types';\n\n// ==================== 类型定义 ====================\n\nexport interface LanguageSwitcherProps {\n variant?: 'buttons' | 'dropdown' | 'icon';\n className?: string;\n onLanguageChange?: (locale: Locale) => void;\n}\n\nexport interface LanguageOption {\n locale: Locale;\n label: string;\n flag: string;\n}\n\n// ==================== 语言选项配置 ====================\n\nconst LANGUAGE_OPTIONS: LanguageOption[] = [\n { locale: 'zh-CN', label: '简体中文', flag: '🇨🇳' },\n { locale: 'zh-TW', label: '繁體中文', flag: '🇹🇼' },\n { locale: 'en-US', label: 'English', flag: '🇺🇸' },\n { locale: 'ja-JP', label: '日本語', flag: '🇯🇵' },\n];\n\n// ==================== 按钮组样式 ====================\n\n/**\n * 按钮组语言切换器\n */\nexport function LanguageSwitcherButtons({\n className = '',\n onLanguageChange,\n}: LanguageSwitcherProps) {\n const { locale, setLocale } = useTranslation();\n\n const handleChange = (newLocale: Locale) => {\n setLocale(newLocale);\n onLanguageChange?.(newLocale);\n };\n\n return (\n <div className={`flex gap-2 flex-wrap ${className}`}>\n {LANGUAGE_OPTIONS.map((option) => (\n <button\n key={option.locale}\n onClick={() => handleChange(option.locale)}\n className={`\n flex items-center gap-2 px-4 py-2 rounded-lg border-2\n transition-all duration-200 font-medium\n ${\n locale === option.locale\n ? 'border-blue-500 bg-blue-50 text-blue-700 shadow-md'\n : 'border-gray-300 bg-white text-gray-700 hover:border-blue-300 hover:bg-blue-50'\n }\n `}\n aria-label={option.label}\n >\n <span className=\"text-xl\">{option.flag}</span>\n <span className=\"text-sm\">{option.label}</span>\n </button>\n ))}\n </div>\n );\n}\n\n// ==================== 下拉菜单样式 ====================\n\n/**\n * 下拉菜单语言切换器\n */\nexport function LanguageSwitcherDropdown({\n className = '',\n onLanguageChange,\n}: LanguageSwitcherProps) {\n const { locale, setLocale, t } = useTranslation();\n\n const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n const newLocale = e.target.value as Locale;\n setLocale(newLocale);\n onLanguageChange?.(newLocale);\n };\n\n return (\n <div className={`flex flex-col gap-2 ${className}`}>\n <label htmlFor=\"language-select\" className=\"text-sm font-medium text-gray-700\">\n {t('language.label')}\n </label>\n <select\n id=\"language-select\"\n value={locale}\n onChange={handleChange}\n className=\"\n px-4 py-2 rounded-lg border-2 border-gray-300 bg-white\n text-gray-700 font-medium cursor-pointer\n focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500\n hover:border-gray-400 transition-colors duration-200\n \"\n aria-label={t('language.label')}\n >\n {LANGUAGE_OPTIONS.map((option) => (\n <option key={option.locale} value={option.locale}>\n {option.flag} {option.label}\n </option>\n ))}\n </select>\n </div>\n );\n}\n\n// ==================== 图标按钮样式 ====================\n\n/**\n * 图标按钮语言切换器(带下拉菜单)\n */\nexport function LanguageSwitcherIcon({ className = '', onLanguageChange }: LanguageSwitcherProps) {\n const { locale, setLocale } = useTranslation();\n const [isOpen, setIsOpen] = React.useState(false);\n\n const currentOption = LANGUAGE_OPTIONS.find((opt) => opt.locale === locale);\n\n const handleChange = (newLocale: Locale) => {\n setLocale(newLocale);\n setIsOpen(false);\n onLanguageChange?.(newLocale);\n };\n\n // 点击外部关闭下拉菜单\n React.useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n const target = event.target as HTMLElement;\n if (!target.closest('.language-switcher-icon-wrapper')) {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n return undefined;\n }, [isOpen]);\n\n return (\n <div className={`relative language-switcher-icon-wrapper ${className}`}>\n <button\n onClick={() => setIsOpen(!isOpen)}\n className=\"\n flex items-center gap-2 px-3 py-2 rounded-lg border-2 border-gray-300\n bg-white hover:border-blue-300 hover:bg-blue-50\n transition-all duration-200 cursor-pointer\n focus:outline-none focus:ring-2 focus:ring-blue-500\n \"\n aria-label=\"Switch Language\"\n aria-expanded={isOpen}\n >\n <span className=\"text-xl\">{currentOption?.flag}</span>\n <span className={`text-gray-600 text-xs transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}>\n ▼\n </span>\n </button>\n\n {isOpen && (\n <div className=\"\n absolute right-0 top-full mt-2 w-48\n bg-white border-2 border-gray-200 rounded-lg shadow-lg\n overflow-hidden z-50\n animate-in fade-in slide-in-from-top-2 duration-200\n \">\n {LANGUAGE_OPTIONS.map((option) => (\n <button\n key={option.locale}\n onClick={() => handleChange(option.locale)}\n className={`\n w-full flex items-center justify-between px-4 py-3\n transition-colors duration-150\n ${\n locale === option.locale\n ? 'bg-blue-50 text-blue-700'\n : 'text-gray-700 hover:bg-gray-50'\n }\n `}\n >\n <div className=\"flex items-center gap-3\">\n <span className=\"text-lg\">{option.flag}</span>\n <span className=\"text-sm font-medium\">{option.label}</span>\n </div>\n {locale === option.locale && (\n <span className=\"text-blue-600 font-bold\">✓</span>\n )}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// ==================== 主组件 ====================\n\n/**\n * 语言切换器主组件\n * 根据 variant 自动选择样式\n */\nexport function LanguageSwitcher({\n variant = 'buttons',\n className,\n onLanguageChange,\n}: LanguageSwitcherProps) {\n switch (variant) {\n case 'dropdown':\n return <LanguageSwitcherDropdown className={className} onLanguageChange={onLanguageChange} />;\n case 'icon':\n return <LanguageSwitcherIcon className={className} onLanguageChange={onLanguageChange} />;\n case 'buttons':\n default:\n return <LanguageSwitcherButtons className={className} onLanguageChange={onLanguageChange} />;\n }\n}\n\n// ==================== 默认导出 ====================\n\nexport default LanguageSwitcher;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qhr123/sa2kit",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "A modern, type-safe React utility library with cross-platform support and platform adapters",
5
5
  "keywords": [
6
6
  "react",