@coffic/cosy-ui 0.3.1-beta.1 → 0.3.2-beta.1

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.
@@ -81,6 +81,8 @@ import Main from '../containers/Main.astro';
81
81
  import Header from './Header.astro';
82
82
  import Sidebar from './Sidebar.astro';
83
83
  import DefaultLogo from '../../assets/logo.png';
84
+ import { getText } from '../../utils/i18n';
85
+ import { getValidLanguage } from '../../utils/language';
84
86
 
85
87
  export interface SidebarItem {
86
88
  href: string;
@@ -362,6 +364,9 @@ const {
362
364
  } = Astro.props;
363
365
 
364
366
  const currentPath = Astro.url.pathname;
367
+
368
+ // 获取有效的语言代码
369
+ const validLang = getValidLanguage(currentLocale);
365
370
  ---
366
371
 
367
372
  <BaseLayout
@@ -405,7 +410,7 @@ const currentPath = Astro.url.pathname;
405
410
  <div class="w-64 shrink-0">
406
411
  <div class="sticky top-16">
407
412
  <slot name="toc">
408
- <TableOfContents />
413
+ <TableOfContents lang={currentLocale} />
409
414
  </slot>
410
415
  </div>
411
416
  </div>
@@ -417,11 +422,12 @@ const currentPath = Astro.url.pathname;
417
422
  {showFooter && (
418
423
  <Footer
419
424
  siteName={siteName}
425
+ lang={currentLocale}
420
426
  homeLink={footerHomeLink || "/"}
421
- slogan={footerSlogan || "优雅、高效的组件库"}
427
+ slogan={footerSlogan || getText(validLang, 'footer', 'slogan') || getText(validLang, 'footer', 'defaultSlogan')}
422
428
  company={footerCompany || siteName}
423
- copyright={footerCopyright || "保留所有权利"}
424
- inspirationalSlogan={footerInspirationalSlogan || "构建美好的数字体验"}
429
+ copyright={footerCopyright || getText(validLang, 'footer', 'copyright')}
430
+ inspirationalSlogan={footerInspirationalSlogan || getText(validLang, 'footer', 'inspirationalSlogan')}
425
431
  aboutLink={footerAboutLink || "/about"}
426
432
  contactLink={footerContactLink || "/contact"}
427
433
  icp={footerIcp}
@@ -12,6 +12,7 @@
12
12
  * 2. 响应式布局 - 在不同屏幕尺寸下保持良好的可用性和美观性
13
13
  * 3. 可定制性 - 支持多种配置选项,适应不同网站的需求
14
14
  * 4. 品牌一致性 - 与网站整体设计风格保持一致
15
+ * 5. 多语言支持 - 支持多种语言显示,自动检测当前语言环境
15
16
  *
16
17
  * 视觉特点:
17
18
  * - 分区布局:清晰区分不同类别的信息
@@ -89,6 +90,27 @@
89
90
  * />
90
91
  * ```
91
92
  *
93
+ * 指定语言:
94
+ * ```astro
95
+ * <Footer
96
+ * siteName="My Website"
97
+ * homeLink="/"
98
+ * slogan="Simple and Powerful"
99
+ * company="My Company"
100
+ * copyright="All Rights Reserved"
101
+ * lang="en"
102
+ * />
103
+ * ```
104
+ *
105
+ * 启用日志:
106
+ * ```astro
107
+ * <Footer
108
+ * siteName="我的网站"
109
+ * homeLink="/"
110
+ * enableLogging={true}
111
+ * />
112
+ * ```
113
+ *
92
114
  * @props
93
115
  * @prop {string} siteName - 网站名称
94
116
  * @prop {string} homeLink - 首页链接
@@ -114,6 +136,8 @@
114
136
  * @prop {string} [mediaLink] - "媒体报道"页面链接
115
137
  * @prop {string} [techStackLink] - "技术栈"页面链接
116
138
  * @prop {boolean} [debug=false] - 调试模式
139
+ * @prop {string} [lang] - 语言代码,默认自动检测
140
+ * @prop {boolean} [enableLogging=false] - 是否启用日志输出
117
141
  *
118
142
  * @accessibility
119
143
  * - 使用语义化HTML结构,确保屏幕阅读器可以正确解析
@@ -125,11 +149,24 @@ import { processSocialLink } from '../../utils/social';
125
149
  import Link from '../base/Link.astro';
126
150
  import SocialIcon from '../icons/SocialIcon.astro';
127
151
  import type { FooterProps } from '../../types/footer';
152
+ import { getCurrentLanguage, LanguageSource } from '../../utils/language';
153
+ import { createTextGetter } from '../../utils/i18n';
128
154
 
129
155
  // 导入样式
130
156
  import '../../app.css';
131
157
 
132
- interface Props extends FooterProps {}
158
+ interface Props extends FooterProps {
159
+ /**
160
+ * 语言代码
161
+ * @default 自动检测
162
+ */
163
+ lang?: string;
164
+ /**
165
+ * 是否启用日志输出
166
+ * @default false
167
+ */
168
+ enableLogging?: boolean;
169
+ }
133
170
 
134
171
  const {
135
172
  siteName,
@@ -156,8 +193,31 @@ const {
156
193
  mediaLink,
157
194
  techStackLink,
158
195
  debug = false,
196
+ lang: userLang,
197
+ enableLogging = false,
159
198
  }: Props = Astro.props;
160
199
 
200
+ // 获取当前语言
201
+ const langInfo = getCurrentLanguage(userLang);
202
+ // 创建文本获取函数
203
+ const t = createTextGetter(langInfo, 'footer');
204
+
205
+ // 获取语言来源的描述
206
+ function getLanguageSourceDescription(source: LanguageSource): string {
207
+ switch (source) {
208
+ case LanguageSource.USER:
209
+ return '用户指定';
210
+ case LanguageSource.URL:
211
+ return 'URL参数';
212
+ case LanguageSource.BROWSER:
213
+ return '浏览器设置';
214
+ case LanguageSource.DEFAULT:
215
+ return '默认语言';
216
+ default:
217
+ return '未知来源';
218
+ }
219
+ }
220
+
161
221
  const currentYear = new Date().getFullYear();
162
222
 
163
223
  // 处理社交链接
@@ -220,7 +280,7 @@ const debugClasses = debug ? {
220
280
  {/* 产品导航 */}
221
281
  {products.length > 0 && (
222
282
  <nav class:list={["h-full", debugClasses.nav]}>
223
- <h6 class="footer-title">产品</h6>
283
+ <h6 class="footer-title">{t('products')}</h6>
224
284
  {products.map((product) => (
225
285
  <Link href={product.href} external={product.external} size='sm' block animation='hover-lift'>
226
286
  {product.name}
@@ -232,32 +292,32 @@ const debugClasses = debug ? {
232
292
  {/* 关于导航 */}
233
293
  {(aboutLink || contactLink || teamLink || careersLink) && (
234
294
  <nav class:list={["h-full", debugClasses.nav]}>
235
- <h6 class="footer-title">关于</h6>
236
- {aboutLink && <Link href={aboutLink} block animation='hover-lift' size='sm'>关于我们</Link>}
237
- {teamLink && <Link href={teamLink} block animation='hover-lift' size='sm'>团队介绍</Link>}
238
- {careersLink && <Link href={careersLink} block animation='hover-lift' size='sm'>加入我们</Link>}
239
- {contactLink && <Link href={contactLink} block animation='hover-lift' size='sm'>联系我们</Link>}
295
+ <h6 class="footer-title">{t('about')}</h6>
296
+ {aboutLink && <Link href={aboutLink} block animation='hover-lift' size='sm'>{t('aboutUs')}</Link>}
297
+ {teamLink && <Link href={teamLink} block animation='hover-lift' size='sm'>{t('team')}</Link>}
298
+ {careersLink && <Link href={careersLink} block animation='hover-lift' size='sm'>{t('careers')}</Link>}
299
+ {contactLink && <Link href={contactLink} block animation='hover-lift' size='sm'>{t('contactUs')}</Link>}
240
300
  </nav>
241
301
  )}
242
302
 
243
303
  {/* 资源导航 */}
244
304
  {(newsLink || historyLink || partnersLink || blogLink || faqLink || mediaLink || techStackLink) && (
245
305
  <nav class:list={["", debugClasses.nav]}>
246
- <h6 class="footer-title">资源</h6>
247
- {newsLink && <Link href={newsLink} block animation='hover-lift' size='sm'>新闻动态</Link>}
248
- {blogLink && <Link href={blogLink} block animation='hover-lift' size='sm'>技术博客</Link>}
249
- {faqLink && <Link href={faqLink} block animation='hover-lift' size='sm'>常见问题</Link>}
250
- {historyLink && <Link href={historyLink} block animation='hover-lift' size='sm'>发展历程</Link>}
251
- {techStackLink && <Link href={techStackLink} block animation='hover-lift' size='sm'>技术栈</Link>}
306
+ <h6 class="footer-title">{t('resources')}</h6>
307
+ {newsLink && <Link href={newsLink} block animation='hover-lift' size='sm'>{t('news')}</Link>}
308
+ {blogLink && <Link href={blogLink} block animation='hover-lift' size='sm'>{t('blog')}</Link>}
309
+ {faqLink && <Link href={faqLink} block animation='hover-lift' size='sm'>{t('faq')}</Link>}
310
+ {historyLink && <Link href={historyLink} block animation='hover-lift' size='sm'>{t('history')}</Link>}
311
+ {techStackLink && <Link href={techStackLink} block animation='hover-lift' size='sm'>{t('techStack')}</Link>}
252
312
  </nav>
253
313
  )}
254
314
 
255
315
  {/* 法律导航 */}
256
316
  {(termsLink || privacyLink) && (
257
317
  <nav class:list={["", debugClasses.nav]}>
258
- <h6 class="footer-title">法律</h6>
259
- {termsLink && <Link href={termsLink} block animation='hover-lift' size='sm'>服务条款</Link>}
260
- {privacyLink && <Link href={privacyLink} block animation='hover-lift' size='sm'>隐私政策</Link>}
318
+ <h6 class="footer-title">{t('legal')}</h6>
319
+ {termsLink && <Link href={termsLink} block animation='hover-lift' size='sm'>{t('terms')}</Link>}
320
+ {privacyLink && <Link href={privacyLink} block animation='hover-lift' size='sm'>{t('privacy')}</Link>}
261
321
  </nav>
262
322
  )}
263
323
  </div>
@@ -275,7 +335,7 @@ const debugClasses = debug ? {
275
335
  <div class:list={["footer footer-center p-4 bg-base-300 text-base-content", debugClasses.footer]}>
276
336
  <aside class:list={["items-center grid-flow-col", debugClasses.aside]}>
277
337
  <p class="text-sm opacity-70">
278
- © {currentYear} {company} - {copyright}
338
+ © {currentYear} {company} - {copyright || t('allRightsReserved')}
279
339
  </p>
280
340
  {icp && (
281
341
  <p class="text-sm opacity-70 ml-4">
@@ -285,6 +345,25 @@ const debugClasses = debug ? {
285
345
  </aside>
286
346
  </div>
287
347
 
348
+ <script define:vars={{ langInfo, enableLogging }}>
349
+ // 输出语言信息到控制台
350
+ if (enableLogging) {
351
+ console.log(`[Footer] 语言信息:`, {
352
+ 语言代码: langInfo.code,
353
+ 语言来源: langInfo.source,
354
+ 来源描述: (() => {
355
+ switch (langInfo.source) {
356
+ case 'user': return '用户指定';
357
+ case 'url': return 'URL参数';
358
+ case 'browser': return '浏览器设置';
359
+ case 'default': return '默认语言';
360
+ default: return '未知来源';
361
+ }
362
+ })()
363
+ });
364
+ }
365
+ </script>
366
+
288
367
  <style scoped>
289
368
  @reference '../../app.css';
290
369
  nav {
@@ -14,6 +14,7 @@
14
14
  * 3. 视觉层次 - 通过缩进和样式区分不同级别的标题
15
15
  * 4. 响应式设计 - 在小屏幕设备上自动隐藏,优化空间利用
16
16
  * 5. 智能显示 - 当页面结构不需要目录时自动隐藏
17
+ * 6. 多语言支持 - 支持多种语言显示,自动检测当前语言环境
17
18
  *
18
19
  * @usage
19
20
  * 基本用法:
@@ -39,10 +40,22 @@
39
40
  * ```astro
40
41
  * <TableOfContents containerSelector=".article-content" />
41
42
  * ```
43
+ *
44
+ * 指定语言:
45
+ * ```astro
46
+ * <TableOfContents lang="zh-cn" />
47
+ * ```
48
+ *
49
+ * 启用日志:
50
+ * ```astro
51
+ * <TableOfContents enableLogging={true} />
52
+ * ```
42
53
  */
43
54
 
44
55
  // 导入样式
45
56
  import '../../app.css';
57
+ import { getCurrentLanguage, LanguageSource } from '../../utils/language';
58
+ import { createTextGetter } from '../../utils/i18n';
46
59
 
47
60
  interface Props {
48
61
  /**
@@ -66,7 +79,7 @@ interface Props {
66
79
  maxDepth?: number;
67
80
  /**
68
81
  * 标题文本
69
- * @default "目录"
82
+ * @default 根据语言自动选择
70
83
  */
71
84
  title?: string;
72
85
  /**
@@ -79,6 +92,16 @@ interface Props {
79
92
  * @default 2
80
93
  */
81
94
  minHeadings?: number;
95
+ /**
96
+ * 语言
97
+ * @default 自动检测
98
+ */
99
+ lang?: string;
100
+ /**
101
+ * 是否启用日志输出
102
+ * @default false
103
+ */
104
+ enableLogging?: boolean;
82
105
  }
83
106
 
84
107
  const {
@@ -86,28 +109,70 @@ const {
86
109
  class: className = '',
87
110
  selector = 'h2, h3',
88
111
  maxDepth = 3,
89
- title = '目录',
90
112
  containerSelector = 'main',
91
113
  minHeadings = 2,
114
+ lang: userLang,
115
+ title,
116
+ enableLogging = true,
92
117
  } = Astro.props;
93
118
 
119
+ // 获取当前语言
120
+ const langInfo = getCurrentLanguage(userLang);
121
+ // 创建文本获取函数
122
+ const t = createTextGetter(langInfo, 'tableOfContents');
123
+ // 获取标题文本,如果用户提供了标题则使用用户提供的标题
124
+ const titleText = title || t('title');
125
+
94
126
  // 生成唯一ID,确保多个TOC实例不会冲突
95
127
  const tocId = `toc-${Math.random().toString(36).substring(2, 9)}`;
128
+
129
+ // 获取语言来源的描述
130
+ function getLanguageSourceDescription(source: LanguageSource): string {
131
+ switch (source) {
132
+ case LanguageSource.USER:
133
+ return '用户指定';
134
+ case LanguageSource.URL:
135
+ return 'URL参数';
136
+ case LanguageSource.BROWSER:
137
+ return '浏览器设置';
138
+ case LanguageSource.DEFAULT:
139
+ return '默认语言';
140
+ default:
141
+ return '未知来源';
142
+ }
143
+ }
96
144
  ---
97
145
 
98
146
  <div class={`toc-container ${fixed ? 'fixed top-20 right-4 w-64' : 'w-full max-w-xs'} ${className}`} id={`${tocId}-container`} style="display: none;">
99
147
  <div class="card bg-base-100 shadow-xl">
100
148
  <div class="card-body p-4">
101
- <div class="card-title text-lg font-bold mb-2">{title}</div>
149
+ <div class="card-title text-lg font-bold mb-2">{titleText}</div>
102
150
  <ul class="menu menu-sm" id={tocId}>
103
151
  <!-- 目录项将通过 JavaScript 动态生成 -->
104
- <li class="text-base-content/60">加载中...</li>
152
+ <li class="text-base-content/60">{t('loading')}</li>
105
153
  </ul>
106
154
  </div>
107
155
  </div>
108
156
  </div>
109
157
 
110
- <script define:vars={{ selector, maxDepth, tocId, containerSelector, minHeadings }}>
158
+ <script define:vars={{ selector, maxDepth, tocId, containerSelector, minHeadings, langInfo, enableLogging }}>
159
+ // 输出语言信息到控制台
160
+ if (enableLogging) {
161
+ console.log(`[TableOfContents] 语言信息:`, {
162
+ 语言代码: langInfo.code,
163
+ 语言来源: langInfo.source,
164
+ 来源描述: (() => {
165
+ switch (langInfo.source) {
166
+ case 'user': return '用户指定';
167
+ case 'url': return 'URL参数';
168
+ case 'browser': return '浏览器设置';
169
+ case 'default': return '默认语言';
170
+ default: return '未知来源';
171
+ }
172
+ })()
173
+ });
174
+ }
175
+
111
176
  // 在页面加载完成后生成目录
112
177
  function generateTOC() {
113
178
  // 使用指定的容器选择器查找内容容器
@@ -34,4 +34,13 @@ export interface FooterProps {
34
34
  faqLink?: string;
35
35
  mediaLink?: string;
36
36
  techStackLink?: string;
37
+ /**
38
+ * 语言代码,默认自动检测
39
+ */
40
+ lang?: string;
41
+ /**
42
+ * 是否启用日志输出
43
+ * @default false
44
+ */
45
+ enableLogging?: boolean;
37
46
  }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * 国际化文本配置
3
+ *
4
+ * 提供组件的多语言文本内容
5
+ */
6
+
7
+ import type { SupportedLanguage, LanguageInfo } from './language';
8
+
9
+ // 定义文本内容的类型
10
+ type TextContent = Record<string, Record<string, string>>;
11
+
12
+ // 多语言文本内容
13
+ export const texts: Record<SupportedLanguage, TextContent> = {
14
+ 'en': {
15
+ tableOfContents: {
16
+ title: 'Table of Contents',
17
+ loading: 'Loading...'
18
+ },
19
+ footer: {
20
+ products: 'Products',
21
+ about: 'About',
22
+ aboutUs: 'About Us',
23
+ team: 'Our Team',
24
+ careers: 'Careers',
25
+ contactUs: 'Contact Us',
26
+ resources: 'Resources',
27
+ news: 'News',
28
+ blog: 'Blog',
29
+ faq: 'FAQ',
30
+ history: 'History',
31
+ techStack: 'Tech Stack',
32
+ legal: 'Legal',
33
+ terms: 'Terms of Service',
34
+ privacy: 'Privacy Policy',
35
+ slogan: 'Build a beautiful digital experience',
36
+ allRightsReserved: 'All Rights Reserved'
37
+ }
38
+ },
39
+ 'zh-cn': {
40
+ tableOfContents: {
41
+ title: '目录',
42
+ loading: '加载中...'
43
+ },
44
+ footer: {
45
+ products: '产品',
46
+ about: '关于',
47
+ aboutUs: '关于我们',
48
+ team: '团队介绍',
49
+ careers: '加入我们',
50
+ contactUs: '联系我们',
51
+ defaultSlogan: '优雅、高效的组件库',
52
+ resources: '资源',
53
+ news: '新闻动态',
54
+ blog: '技术博客',
55
+ faq: '常见问题',
56
+ history: '发展历程',
57
+ techStack: '技术栈',
58
+ legal: '法律',
59
+ terms: '服务条款',
60
+ privacy: '隐私政策',
61
+ allRightsReserved: '保留所有权利'
62
+ }
63
+ }
64
+ };
65
+
66
+ /**
67
+ * 获取指定语言的文本内容
68
+ * @param lang 语言代码
69
+ * @param component 组件名称
70
+ * @param key 文本键名
71
+ * @returns 对应的文本内容
72
+ */
73
+ export function getText(lang: SupportedLanguage, component: string, key: string): string {
74
+ return texts[lang]?.[component]?.[key] || texts['en'][component]?.[key] || '';
75
+ }
76
+
77
+ /**
78
+ * 创建组件的文本获取函数
79
+ * @param langInfo 语言信息
80
+ * @param component 组件名称
81
+ * @returns 文本获取函数
82
+ */
83
+ export function createTextGetter(langInfo: LanguageInfo, component: string) {
84
+ return (key: string): string => getText(langInfo.code, component, key);
85
+ }
@@ -0,0 +1,156 @@
1
+ /**
2
+ * 语言工具模块
3
+ *
4
+ * 提供语言相关的工具函数,用于多语言支持
5
+ */
6
+
7
+ // 支持的语言列表
8
+ export const SUPPORTED_LANGUAGES = ['en', 'zh-cn'] as const;
9
+ export type SupportedLanguage = typeof SUPPORTED_LANGUAGES[number];
10
+
11
+ // 语言来源枚举
12
+ export enum LanguageSource {
13
+ USER = 'user', // 用户指定
14
+ URL = 'url', // 从URL获取
15
+ BROWSER = 'browser', // 从浏览器设置获取
16
+ DEFAULT = 'default' // 默认语言
17
+ }
18
+
19
+ // 语言信息接口
20
+ export interface LanguageInfo {
21
+ code: SupportedLanguage; // 语言代码
22
+ source: LanguageSource; // 语言来源
23
+ }
24
+
25
+ // 默认语言
26
+ export const DEFAULT_LANGUAGE: SupportedLanguage = 'en';
27
+
28
+ /**
29
+ * 检查语言是否被支持
30
+ * @param lang 要检查的语言代码
31
+ * @returns 如果语言被支持返回true,否则返回false
32
+ */
33
+ export function isLanguageSupported(lang?: string): lang is SupportedLanguage {
34
+ if (!lang) return false;
35
+ return SUPPORTED_LANGUAGES.includes(lang as SupportedLanguage);
36
+ }
37
+
38
+ /**
39
+ * 获取有效的语言代码
40
+ * @param lang 用户提供的语言代码
41
+ * @returns 有效的语言代码,如果提供的语言不支持则返回默认语言
42
+ */
43
+ export function getValidLanguage(lang?: string): SupportedLanguage {
44
+ if (lang && isLanguageSupported(lang)) {
45
+ return lang;
46
+ }
47
+ return DEFAULT_LANGUAGE;
48
+ }
49
+
50
+ /**
51
+ * 从URL中提取语言代码
52
+ * @returns 从URL中提取的语言代码,如果无法提取则返回undefined
53
+ */
54
+ function getLanguageFromURL(): string | undefined {
55
+ if (typeof window === 'undefined') return undefined;
56
+
57
+ // 尝试从路径中提取语言代码
58
+ // 例如: /zh-cn/components/button
59
+ const pathMatch = window.location.pathname.match(/^\/([\w-]+)\//);
60
+ if (pathMatch && isLanguageSupported(pathMatch[1])) {
61
+ return pathMatch[1];
62
+ }
63
+
64
+ // 尝试从查询参数中提取语言代码
65
+ // 例如: ?lang=zh-cn
66
+ const urlParams = new URLSearchParams(window.location.search);
67
+ const langParam = urlParams.get('lang');
68
+ if (langParam && isLanguageSupported(langParam)) {
69
+ return langParam;
70
+ }
71
+
72
+ return undefined;
73
+ }
74
+
75
+ /**
76
+ * 从浏览器设置中获取首选语言
77
+ * @returns 从浏览器设置中获取的语言代码,如果无法获取则返回undefined
78
+ */
79
+ function getLanguageFromBrowser(): string | undefined {
80
+ if (typeof navigator === 'undefined') return undefined;
81
+
82
+ // 获取浏览器语言
83
+ const browserLang = navigator.language.toLowerCase();
84
+
85
+ // 检查完整匹配
86
+ if (isLanguageSupported(browserLang)) {
87
+ return browserLang;
88
+ }
89
+
90
+ // 检查语言前缀匹配
91
+ // 例如: zh-TW -> zh-cn
92
+ const langPrefix = browserLang.split('-')[0];
93
+ for (const lang of SUPPORTED_LANGUAGES) {
94
+ if (lang.startsWith(langPrefix)) {
95
+ return lang;
96
+ }
97
+ }
98
+
99
+ return undefined;
100
+ }
101
+
102
+ /**
103
+ * 自动检测当前语言
104
+ * @returns 检测到的语言信息,包括语言代码和来源
105
+ */
106
+ export function detectLanguage(): LanguageInfo {
107
+ // 尝试从URL中获取语言
108
+ const urlLang = getLanguageFromURL();
109
+ if (urlLang) {
110
+ return {
111
+ code: urlLang as SupportedLanguage,
112
+ source: LanguageSource.URL
113
+ };
114
+ }
115
+
116
+ // 尝试从浏览器设置中获取语言
117
+ const browserLang = getLanguageFromBrowser();
118
+ if (browserLang) {
119
+ return {
120
+ code: browserLang as SupportedLanguage,
121
+ source: LanguageSource.BROWSER
122
+ };
123
+ }
124
+
125
+ // 如果无法检测,返回默认语言
126
+ return {
127
+ code: DEFAULT_LANGUAGE,
128
+ source: LanguageSource.DEFAULT
129
+ };
130
+ }
131
+
132
+ /**
133
+ * 获取当前语言
134
+ * @param userLang 用户指定的语言(可选)
135
+ * @returns 当前应使用的语言信息,包括语言代码和来源
136
+ */
137
+ export function getCurrentLanguage(userLang?: string): LanguageInfo {
138
+ // 如果用户指定了语言,优先使用用户指定的语言
139
+ if (userLang) {
140
+ if (isLanguageSupported(userLang)) {
141
+ return {
142
+ code: userLang as SupportedLanguage,
143
+ source: LanguageSource.USER
144
+ };
145
+ } else {
146
+ // 用户指定的语言不支持,使用默认语言
147
+ return {
148
+ code: DEFAULT_LANGUAGE,
149
+ source: LanguageSource.DEFAULT
150
+ };
151
+ }
152
+ }
153
+
154
+ // 否则自动检测语言
155
+ return detectLanguage();
156
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffic/cosy-ui",
3
- "version": "0.3.1-beta.1",
3
+ "version": "0.3.2-beta.1",
4
4
  "description": "An astro component library",
5
5
  "author": {
6
6
  "name": "nookery",