@lobehub/chat 0.84.0 → 0.85.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.
Files changed (43) hide show
  1. package/.github/workflows/lighthouse-badger-advanced.yml +11 -29
  2. package/.github/workflows/pre-welcome.yml +22 -0
  3. package/.github/workflows/sync.yml +7 -3
  4. package/.i18nrc.js +1 -2
  5. package/CHANGELOG.md +50 -0
  6. package/locales/ja_JP/common.json +103 -0
  7. package/locales/ja_JP/empty.json +6 -0
  8. package/locales/ja_JP/error.json +42 -0
  9. package/locales/ja_JP/market.json +16 -0
  10. package/locales/ja_JP/plugin.json +107 -0
  11. package/locales/ja_JP/setting.json +225 -0
  12. package/locales/ja_JP/welcome.json +14 -0
  13. package/locales/ko_KR/common.json +103 -0
  14. package/locales/ko_KR/empty.json +6 -0
  15. package/locales/ko_KR/error.json +42 -0
  16. package/locales/ko_KR/market.json +16 -0
  17. package/locales/ko_KR/plugin.json +107 -0
  18. package/locales/ko_KR/setting.json +225 -0
  19. package/locales/ko_KR/welcome.json +14 -0
  20. package/package.json +1 -1
  21. package/public/icons/maskable-icon-192x192.png +0 -0
  22. package/public/icons/maskable-icon-512x512.png +0 -0
  23. package/public/manifest.json +34 -5
  24. package/public/screenshots/screenshot-1.png +0 -0
  25. package/public/screenshots/screenshot-2.png +0 -0
  26. package/public/screenshots/screenshot-3.png +0 -0
  27. package/public/screenshots/screenshot-4.png +0 -0
  28. package/src/app/chat/features/ChatInputContent/Footer/SaveTopic.tsx +1 -1
  29. package/src/app/welcome/(desktop)/features/Footer.tsx +14 -3
  30. package/src/app/welcome/(desktop)/layout.desktop.tsx +1 -4
  31. package/src/app/welcome/features/Banner/index.tsx +16 -17
  32. package/src/const/layoutTokens.ts +1 -1
  33. package/src/const/url.ts +2 -1
  34. package/src/features/SideBar/BottomActions.tsx +9 -2
  35. package/src/layout/AppLayout.mobile.tsx +1 -0
  36. package/src/layout/GlobalLayout/AppTheme.tsx +3 -3
  37. package/src/layout/GlobalLayout/Locale.tsx +2 -2
  38. package/src/locales/options.ts +8 -1
  39. package/src/locales/resources/index.ts +4 -0
  40. package/src/locales/resources/ja_JP.ts +19 -0
  41. package/src/locales/resources/ko_KR.ts +19 -0
  42. package/src/utils/VersionController.ts +1 -1
  43. package/src/utils/responsive.ts +1 -1
@@ -0,0 +1,225 @@
1
+ {
2
+ "danger": {
3
+ "clear": {
4
+ "action": "지금 지우기",
5
+ "confirm": "모든 채팅 데이터를 지우시겠습니까?",
6
+ "desc": "모든 대화 데이터를 지웁니다.",
7
+ "success": "모든 대화 메시지가 지워졌습니다.",
8
+ "title": "모든 대화 메시지 지우기"
9
+ },
10
+ "reset": {
11
+ "action": "지금 재설정",
12
+ "confirm": "모든 설정을 재설정하시겠습니까?",
13
+ "currentVersion": "현재 버전",
14
+ "desc": "모든 설정 항목을 기본값으로 재설정합니다.",
15
+ "title": "모든 설정 재설정"
16
+ }
17
+ },
18
+ "header": {
19
+ "global": "전역 설정",
20
+ "session": "세션 설정",
21
+ "sessionWithName": "세션 설정 · {{name}}"
22
+ },
23
+ "llm": {
24
+ "AzureOpenAI": {
25
+ "endpoint": {
26
+ "desc": "Azure 포털에서 리소스를 확인할 때 이 값을 '키 및 엔드포인트' 섹션에서 찾을 수 있습니다.",
27
+ "placeholder": "https://docs-test-001.openai.azure.com",
28
+ "title": "Azure API 주소"
29
+ },
30
+ "models": {
31
+ "desc": "지원되는 모델",
32
+ "title": "모델 목록"
33
+ },
34
+ "title": "Azure OpenAI 설정",
35
+ "token": {
36
+ "desc": "Azure 포털에서 리소스를 확인할 때 이 값을 '키 및 엔드포인트' 섹션에서 찾을 수 있습니다. KEY1 또는 KEY2를 사용할 수 있습니다.",
37
+ "placeholder": "Azure API 키",
38
+ "title": "API 키"
39
+ }
40
+ },
41
+ "OpenAI": {
42
+ "azureApiVersion": {
43
+ "desc": "Azure의 API 버전입니다. YYYY-MM-DD 형식을 따릅니다. [최신 버전](https://learn.microsoft.com/ko-kr/azure/ai-services/openai/reference#chat-completions)을 확인하세요.",
44
+ "fetch": "목록 가져오기",
45
+ "title": "Azure API 버전"
46
+ },
47
+ "check": {
48
+ "button": "확인",
49
+ "desc": "API 키와 프록시 주소가 올바르게 입력되었는지 테스트합니다.",
50
+ "pass": "확인 완료",
51
+ "title": "연결성 확인"
52
+ },
53
+ "endpoint": {
54
+ "desc": "기본 주소 외에도 반드시 http(s)://를 포함해야 합니다.",
55
+ "placeholder": "https://api.openai.com/v1",
56
+ "title": "인터페이스 프록시 주소"
57
+ },
58
+ "models": {
59
+ "count": "총 {{count}}개의 모델 지원",
60
+ "desc": "지원되는 모델",
61
+ "fetch": "모델 목록 가져오기",
62
+ "notSupport": "Azure OpenAI에서 모델 목록을 볼 수 없습니다.",
63
+ "notSupportTip": "배포 이름과 모델 이름이 일치하는지 확인해야 합니다.",
64
+ "refetch": "모델 목록 다시 가져오기",
65
+ "title": "모델 목록"
66
+ },
67
+ "title": "OpenAI 설정",
68
+ "token": {
69
+ "desc": "자체 OpenAI 키 사용",
70
+ "placeholder": "OpenAI API 키",
71
+ "title": "API 키"
72
+ },
73
+ "useAzure": {
74
+ "desc": "Azure에서 제공하는 OpenAI 서비스 사용",
75
+ "fetch": "목록 가져오기",
76
+ "serverConfig": "관리자가 서버에서 Azure OpenAI를 구성했으므로 변경이 금지되었습니다.",
77
+ "title": "Azure OpenAI"
78
+ }
79
+ },
80
+ "waitingForMore": "더 많은 모델이 <1>계획 중</1>에 있으니 기대해주세요 ✨"
81
+ },
82
+ "settingAgent": {
83
+ "avatar": {
84
+ "title": "아바타"
85
+ },
86
+ "backgroundColor": {
87
+ "title": "배경색"
88
+ },
89
+ "description": {
90
+ "placeholder": "도우미 설명을 입력하세요.",
91
+ "title": "도우미 설명"
92
+ },
93
+ "name": {
94
+ "placeholder": "도우미 이름을 입력하세요.",
95
+ "title": "이름"
96
+ },
97
+ "prompt": {
98
+ "placeholder": "역할 프롬프트 힌트를 입력하세요.",
99
+ "title": "역할 설정"
100
+ },
101
+ "tag": {
102
+ "placeholder": "태그를 입력하세요.",
103
+ "title": "태그"
104
+ },
105
+ "title": "도우미 정보"
106
+ },
107
+ "settingChat": {
108
+ "chatStyleType": {
109
+ "title": "채팅 창 스타일",
110
+ "type": {
111
+ "chat": "대화 모드",
112
+ "docs": "문서 모드"
113
+ }
114
+ },
115
+ "compressThreshold": {
116
+ "desc": "압축되지 않은 이전 메시지가이 값보다 크면 압축됩니다.",
117
+ "title": "압축 임계값"
118
+ },
119
+ "enableCompressThreshold": {
120
+ "title": "이전 메시지 길이 압축 사용"
121
+ },
122
+ "enableHistoryCount": {
123
+ "alias": "제한 없음",
124
+ "limited": "대화 메시지 {{number}} 개만 포함",
125
+ "title": "대화 메시지 제한",
126
+ "unlimited": "대화 메시지 제한 없음"
127
+ },
128
+ "historyCount": {
129
+ "desc": "요청당 포함되는 이전 메시지 수",
130
+ "title": "포함된 이전 메시지 수"
131
+ },
132
+ "inputTemplate": {
133
+ "desc": "사용자의 최신 메시지가이 템플릿에 채워집니다.",
134
+ "placeholder": "사전 처리 템플릿 {{text}}은(는) 실시간 입력 정보로 대체됩니다.",
135
+ "title": "사용자 입력 사전 처리"
136
+ },
137
+ "title": "채팅 설정"
138
+ },
139
+ "settingModel": {
140
+ "enableMaxTokens": {
141
+ "title": "단일 응답 제한 사용"
142
+ },
143
+ "frequencyPenalty": {
144
+ "desc": "값이 클수록 반복 단어가 줄어듭니다.",
145
+ "title": "빈도 패널티"
146
+ },
147
+ "maxTokens": {
148
+ "desc": "단일 상호 작용에 사용되는 최대 토큰 수",
149
+ "title": "단일 응답 제한"
150
+ },
151
+ "model": {
152
+ "desc": "ChatGPT 모델",
153
+ "list": {
154
+ "gpt-3.5-turbo": "GPT 3.5",
155
+ "gpt-3.5-turbo-16k": "GPT 3.5 (16K)",
156
+ "gpt-4": "GPT 4",
157
+ "gpt-4-32k": "GPT 4 (32K)"
158
+ },
159
+ "title": "모델"
160
+ },
161
+ "presencePenalty": {
162
+ "desc": "값이 클수록 새로운 주제로 확장될 가능성이 높아집니다.",
163
+ "title": "주제 신선도"
164
+ },
165
+ "temperature": {
166
+ "desc": "값이 클수록 응답이 더 무작위 해집니다.",
167
+ "title": "랜덤성",
168
+ "titleWithValue": "랜덤성 {{value}}"
169
+ },
170
+ "title": "모델 설정",
171
+ "topP": {
172
+ "desc": "랜덤성과 유사하지만 함께 변경하지 마십시오.",
173
+ "title": "상위 P 샘플링"
174
+ }
175
+ },
176
+ "settingPlugin": {
177
+ "add": "추가",
178
+ "addTooltip": "사용자 정의 플러그인 추가",
179
+ "clearDeprecated": "사용되지 않는 플러그인 제거",
180
+ "config": "{{id}} 플러그인 구성",
181
+ "settings": "플러그인 마켓 설정",
182
+ "title": "플러그인 목록"
183
+ },
184
+ "settingSystem": {
185
+ "accessCode": {
186
+ "desc": "관리자가 암호 액세스를 활성화했습니다.",
187
+ "placeholder": "액세스 코드를 입력하세요.",
188
+ "title": "액세스 코드"
189
+ },
190
+ "title": "시스템 설정"
191
+ },
192
+ "settingTheme": {
193
+ "avatar": {
194
+ "title": "아바타"
195
+ },
196
+ "fontSize": {
197
+ "desc": "채팅 콘텐츠의 글꼴 크기",
198
+ "title": "글꼴 크기"
199
+ },
200
+ "lang": {
201
+ "autoMode": "시스템에 따름",
202
+ "title": "언어"
203
+ },
204
+ "neutralColor": {
205
+ "desc": "다양한 색상 경향의 중립적인 사용자 정의",
206
+ "title": "중립 색상"
207
+ },
208
+ "primaryColor": {
209
+ "desc": "사용자 정의 테마 색상",
210
+ "title": "테마 색상"
211
+ },
212
+ "themeMode": {
213
+ "auto": "자동",
214
+ "dark": "다크",
215
+ "light": "라이트",
216
+ "title": "테마"
217
+ },
218
+ "title": "테마 설정"
219
+ },
220
+ "tab": {
221
+ "agent": "기본 도우미",
222
+ "common": "일반 설정",
223
+ "llm": "언어 모델"
224
+ }
225
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "button": {
3
+ "import": "구성 가져오기",
4
+ "start": "지금 시작"
5
+ },
6
+ "header": "환영합니다",
7
+ "pickAgent": "또는 다음 도우미 템플릿 중 하나를 선택하세요",
8
+ "skip": "생성 건너뛰기",
9
+ "slogan": {
10
+ "desc1": "뇌 클러스터를 시작하여 아이디어를 자극하세요. 당신의 지능형 어시스턴트가 항상 여기에 있습니다.",
11
+ "desc2": "첫 번째 어시스턴트를 만들어 보세요. 시작해 봅시다~",
12
+ "title": "더 똑똑한 뇌를 위해 스스로에게 선물하세요"
13
+ }
14
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.84.0",
3
+ "version": "0.85.1",
4
4
  "description": "An open-source, extensible (Function Calling), high-performance chatbot framework. It supports one-click free deployment of your private ChatGPT/LLM web application",
5
5
  "keywords": [
6
6
  "chatbot",
@@ -6,12 +6,26 @@
6
6
  {
7
7
  "src": "/icons/icon-192x192.png",
8
8
  "sizes": "192x192",
9
- "type": "image/png"
9
+ "type": "image/png",
10
+ "purpose": "any"
11
+ },
12
+ {
13
+ "src": "/icons/maskable-icon-192x192.png",
14
+ "sizes": "192x192",
15
+ "type": "image/png",
16
+ "purpose": "maskable"
10
17
  },
11
18
  {
12
19
  "src": "/icons/icon-512x512.png",
13
20
  "sizes": "512x512",
14
- "type": "image/png"
21
+ "type": "image/png",
22
+ "purpose": "any"
23
+ },
24
+ {
25
+ "src": "/icons/maskable-icon-512x512.png",
26
+ "sizes": "512x512",
27
+ "type": "image/png",
28
+ "purpose": "maskable"
15
29
  }
16
30
  ],
17
31
  "id": "/",
@@ -20,13 +34,28 @@
20
34
  "scope": "/",
21
35
  "screenshots": [
22
36
  {
23
- "src": "https://registry.npmmirror.com/@lobehub/assets-favicons/1.4.0/files/assets/og-960x540.png",
24
- "sizes": "960x540",
37
+ "src": "/screenshots/screenshot-1.png",
38
+ "sizes": "750x1334",
39
+ "type": "image/png"
40
+ },
41
+ {
42
+ "src": "/screenshots/screenshot-2.png",
43
+ "sizes": "750x1334",
44
+ "type": "image/png"
45
+ },
46
+ {
47
+ "src": "/screenshots/screenshot-3.png",
48
+ "sizes": "750x1334",
49
+ "type": "image/png"
50
+ },
51
+ {
52
+ "src": "/screenshots/screenshot-4.png",
53
+ "sizes": "750x1334",
25
54
  "type": "image/png"
26
55
  }
27
56
  ],
28
57
  "short_name": "LobeChat",
29
58
  "splash_pages": null,
30
- "start_url": "/",
59
+ "start_url": ".",
31
60
  "theme_color": "#000000"
32
61
  }
@@ -19,7 +19,7 @@ const SaveTopic = memo(() => {
19
19
 
20
20
  return (
21
21
  <Tooltip title={t('topic.saveCurrentMessages')}>
22
- <Render icon={icon} onClick={saveToTopic} />
22
+ <Render aria-label={t('topic.saveCurrentMessages')} icon={icon} onClick={saveToTopic} />
23
23
  </Tooltip>
24
24
  );
25
25
  });
@@ -6,7 +6,7 @@ import { Book, Github } from 'lucide-react';
6
6
  import { memo } from 'react';
7
7
  import { Flexbox } from 'react-layout-kit';
8
8
 
9
- import { CHANGELOG, DISCORD, GITHUB } from '@/const/url';
9
+ import { DISCORD, GITHUB, WIKI } from '@/const/url';
10
10
 
11
11
  const Footer = memo(() => {
12
12
  const theme = useTheme();
@@ -21,9 +21,20 @@ const Footer = memo(() => {
21
21
  icon={DiscordIcon}
22
22
  onClick={() => window.open(DISCORD, '__blank')}
23
23
  size={'site'}
24
+ title={'Discord'}
25
+ />
26
+ <ActionIcon
27
+ icon={Book}
28
+ onClick={() => window.open(WIKI, '__blank')}
29
+ size={'site'}
30
+ title={'Wiki'}
31
+ />
32
+ <ActionIcon
33
+ icon={Github}
34
+ onClick={() => window.open(GITHUB, '__blank')}
35
+ size={'site'}
36
+ title={'GitHub'}
24
37
  />
25
- <ActionIcon icon={Book} onClick={() => window.open(CHANGELOG, '__blank')} size={'site'} />
26
- <ActionIcon icon={Github} onClick={() => window.open(GITHUB, '__blank')} size={'site'} />
27
38
  </Flexbox>
28
39
  </Flexbox>
29
40
  );
@@ -1,5 +1,4 @@
1
1
  import { Logo } from '@lobehub/ui';
2
- import Link from 'next/link';
3
2
  import { PropsWithChildren, memo } from 'react';
4
3
  import { Center, Flexbox } from 'react-layout-kit';
5
4
 
@@ -18,9 +17,7 @@ const Desktop = memo<PropsWithChildren>(({ children }) => {
18
17
  horizontal
19
18
  style={{ position: 'relative' }}
20
19
  >
21
- <Link href={'/'}>
22
- <Logo className={styles.logo} size={36} type={'text'} />
23
- </Link>
20
+ <Logo className={styles.logo} size={36} type={'text'} />
24
21
  <Flexbox className={styles.view} flex={1}>
25
22
  {children}
26
23
  </Flexbox>
@@ -4,12 +4,10 @@ import { Icon } from '@lobehub/ui';
4
4
  import { useSize } from 'ahooks';
5
5
  import { Button, Upload } from 'antd';
6
6
  import { SendHorizonal } from 'lucide-react';
7
- import Link from 'next/link';
8
7
  import { memo, useCallback, useRef } from 'react';
9
8
  import { useTranslation } from 'react-i18next';
10
9
  import { Flexbox } from 'react-layout-kit';
11
10
 
12
- import { SESSION_CHAT_URL } from '@/const/url';
13
11
  import { useImportConfig } from '@/hooks/useImportConfig';
14
12
  import { useSessionStore } from '@/store/session';
15
13
 
@@ -23,8 +21,12 @@ const Banner = memo<{ mobile?: boolean }>(({ mobile }) => {
23
21
  const width = domSize?.width || 1024;
24
22
  const { t } = useTranslation('welcome');
25
23
  const { styles } = useStyles();
26
-
27
- const switchSession = useSessionStore((s) => s.switchSession);
24
+ const [switchSession, switchBackToChat, router, isMobile] = useSessionStore((s) => [
25
+ s.switchSession,
26
+ s.switchBackToChat,
27
+ s.router,
28
+ s.isMobile,
29
+ ]);
28
30
  const handleImport = useCallback((e: any) => {
29
31
  importConfig(e);
30
32
  switchSession();
@@ -47,20 +49,17 @@ const Banner = memo<{ mobile?: boolean }>(({ mobile }) => {
47
49
  {t('button.import')}
48
50
  </Button>
49
51
  </Upload>
50
- <Link
51
- href={SESSION_CHAT_URL()}
52
- onClick={(e) => {
53
- e.preventDefault();
54
- switchSession();
55
- }}
52
+ <Button
53
+ block={mobile}
54
+ onClick={() => (isMobile ? router?.push('/chat') : switchBackToChat())}
55
+ size={'large'}
56
+ type={'primary'}
56
57
  >
57
- <Button block={mobile} size={'large'} type={'primary'}>
58
- <Flexbox align={'center'} gap={4} horizontal justify={'center'}>
59
- {t('button.start')}
60
- <Icon icon={SendHorizonal} />
61
- </Flexbox>
62
- </Button>
63
- </Link>
58
+ <Flexbox align={'center'} gap={4} horizontal justify={'center'}>
59
+ {t('button.start')}
60
+ <Icon icon={SendHorizonal} />
61
+ </Flexbox>
62
+ </Button>
64
63
  </Flexbox>
65
64
  </>
66
65
  );
@@ -2,7 +2,7 @@ import type { FormProps } from '@lobehub/ui';
2
2
 
3
3
  export const HEADER_HEIGHT = 64;
4
4
  export const MOBILE_NABBAR_HEIGHT = 44;
5
- export const MOBILE_TABBAR_HEIGHT = 48;
5
+ export const MOBILE_TABBAR_HEIGHT = 60;
6
6
  export const CHAT_TEXTAREA_HEIGHT = 200;
7
7
  export const CHAT_TEXTAREA_HEIGHT_MOBILE = 120;
8
8
  export const CHAT_SIDEBAR_WIDTH = 280;
package/src/const/url.ts CHANGED
@@ -8,7 +8,8 @@ import { DEFAULT_LANG, checkLang } from './locale';
8
8
  import { INBOX_SESSION_ID } from './session';
9
9
 
10
10
  export const GITHUB = pkg.homepage;
11
- export const CHANGELOG = `${pkg.homepage}/blob/master/CHANGELOG.md`;
11
+ export const CHANGELOG = urlJoin(GITHUB, 'blob/master/CHANGELOG.md');
12
+ export const WIKI = urlJoin(GITHUB, 'wiki');
12
13
  export const ABOUT = pkg.homepage;
13
14
  export const FEEDBACK = pkg.bugs.url;
14
15
  export const DISCORD = 'https://discord.gg/AYFPHvv2jT';
@@ -1,6 +1,7 @@
1
1
  import { ActionIcon, DiscordIcon, Icon } from '@lobehub/ui';
2
2
  import { Badge, ConfigProvider, Dropdown, MenuProps, Upload } from 'antd';
3
3
  import {
4
+ Book,
4
5
  Feather,
5
6
  FileClock,
6
7
  Github,
@@ -15,7 +16,7 @@ import { memo } from 'react';
15
16
  import { useTranslation } from 'react-i18next';
16
17
  import { Flexbox } from 'react-layout-kit';
17
18
 
18
- import { ABOUT, CHANGELOG, DISCORD, FEEDBACK, GITHUB } from '@/const/url';
19
+ import { ABOUT, CHANGELOG, DISCORD, FEEDBACK, GITHUB, WIKI } from '@/const/url';
19
20
  import { useExportConfig } from '@/hooks/useExportConfig';
20
21
  import { useImportConfig } from '@/hooks/useImportConfig';
21
22
  import { GlobalStore, useGlobalStore } from '@/store/global';
@@ -94,6 +95,12 @@ const BottomActions = memo<BottomActionProps>(({ tab, setTab }) => {
94
95
  label: t('changelog'),
95
96
  onClick: () => window.open(CHANGELOG, '__blank'),
96
97
  },
98
+ {
99
+ icon: <Icon icon={Book} />,
100
+ key: 'wiki',
101
+ label: 'WIKI',
102
+ onClick: () => window.open(WIKI, '__blank'),
103
+ },
97
104
  {
98
105
  icon: <Icon icon={Heart} />,
99
106
  key: 'about',
@@ -130,7 +137,7 @@ const BottomActions = memo<BottomActionProps>(({ tab, setTab }) => {
130
137
  icon={Github}
131
138
  onClick={() => window.open(GITHUB, '__blank')}
132
139
  placement={'right'}
133
- title={'Github'}
140
+ title={'GitHub'}
134
141
  />
135
142
  <Dropdown arrow={false} menu={{ items }} trigger={['click']}>
136
143
  {hasNewVersion ? (
@@ -62,6 +62,7 @@ const AppLayoutMobile = memo<AppMobileLayoutProps>(
62
62
  <MobileTabBar className={styles.mobileTabBar} />
63
63
  </>
64
64
  )}
65
+ <SafeSpacing mobile position={'bottom'} />
65
66
  </Flexbox>
66
67
  );
67
68
  },
@@ -20,9 +20,9 @@ export interface AppThemeProps {
20
20
 
21
21
  const AppTheme = memo<AppThemeProps>(
22
22
  ({ children, defaultAppearance, defaultPrimaryColor, defaultNeutralColor }) => {
23
- // console.log('server:appearance', defaultAppearance);
24
- // console.log('server:primaryColor', defaultPrimaryColor);
25
- // console.log('server:neutralColor', defaultNeutralColor);
23
+ // console.debug('server:appearance', defaultAppearance);
24
+ // console.debug('server:primaryColor', defaultPrimaryColor);
25
+ // console.debug('server:neutralColor', defaultNeutralColor);
26
26
  const themeMode = useGlobalStore((s) => s.settings.themeMode);
27
27
 
28
28
  const [primaryColor, neutralColor] = useGlobalStore((s) => [
@@ -20,9 +20,9 @@ const InnerLocale = memo<LocaleLayoutProps>(({ children, lang }) => {
20
20
  } else {
21
21
  // if on browser side, init i18n instance only once
22
22
  if (!i18n.instance.isInitialized)
23
- // console.log('locale', lang);
23
+ // console.debug('locale', lang);
24
24
  i18n.init().then(() => {
25
- // console.log('inited.');
25
+ // console.debug('inited.');
26
26
  });
27
27
  }
28
28
 
@@ -1,4 +1,3 @@
1
-
2
1
  import type { Locales } from '@/types/locale';
3
2
 
4
3
  type LocaleOptions = {
@@ -19,6 +18,14 @@ export const localeOptions: LocaleOptions = [
19
18
  label: 'English',
20
19
  value: 'en-US',
21
20
  },
21
+ {
22
+ label: '日本語',
23
+ value: 'ja-JP',
24
+ },
25
+ {
26
+ label: '한국어',
27
+ value: 'ko-KR',
28
+ },
22
29
  {
23
30
  label: 'Russian',
24
31
  value: 'ru-RU',
@@ -1,10 +1,14 @@
1
1
  import en_US from './en_US';
2
+ import ja_JP from './ja_JP';
3
+ import ko_KR from './ko_KR';
2
4
  import ru_RU from './ru_RU';
3
5
  import zh_CN from './zh_CN';
4
6
  import zh_TW from './zh_TW';
5
7
 
6
8
  const resources = {
7
9
  'en-US': en_US,
10
+ 'ja-JP': ja_JP,
11
+ 'ko-KR': ko_KR,
8
12
  'ru-RU': ru_RU,
9
13
  'zh-CN': zh_CN,
10
14
  'zh-TW': zh_TW,
@@ -0,0 +1,19 @@
1
+ import common from '../../../locales/ja_JP/common.json';
2
+ import empty from '../../../locales/ja_JP/empty.json';
3
+ import error from '../../../locales/ja_JP/error.json';
4
+ import market from '../../../locales/ja_JP/market.json';
5
+ import plugin from '../../../locales/ja_JP/plugin.json';
6
+ import setting from '../../../locales/ja_JP/setting.json';
7
+ import welcome from '../../../locales/ja_JP/welcome.json';
8
+
9
+ const resources = {
10
+ common,
11
+ empty,
12
+ error,
13
+ market,
14
+ plugin,
15
+ setting,
16
+ welcome,
17
+ } as const;
18
+
19
+ export default resources;
@@ -0,0 +1,19 @@
1
+ import common from '../../../locales/ko_KR/common.json';
2
+ import empty from '../../../locales/ko_KR/empty.json';
3
+ import error from '../../../locales/ko_KR/error.json';
4
+ import market from '../../../locales/ko_KR/market.json';
5
+ import plugin from '../../../locales/ko_KR/plugin.json';
6
+ import setting from '../../../locales/ko_KR/setting.json';
7
+ import welcome from '../../../locales/ko_KR/welcome.json';
8
+
9
+ const resources = {
10
+ common,
11
+ empty,
12
+ error,
13
+ market,
14
+ plugin,
15
+ setting,
16
+ welcome,
17
+ } as const;
18
+
19
+ export default resources;
@@ -56,7 +56,7 @@ export class VersionController<T> {
56
56
  nextData = migration.migrate(nextData);
57
57
 
58
58
  nextData.version += 1;
59
- console.log('迁移器:', migration, '数据:', nextData, '迁移后版本:', nextData.version);
59
+ console.debug('迁移器:', migration, '数据:', nextData, '迁移后版本:', nextData.version);
60
60
  }
61
61
 
62
62
  return nextData;
@@ -12,7 +12,7 @@ export const isMobileDevice = () => {
12
12
  const { get } = headers();
13
13
  const ua = get('user-agent');
14
14
 
15
- // console.log(ua);
15
+ // console.debug(ua);
16
16
  const device = new UAParser(ua || '').getDevice();
17
17
 
18
18
  return device.type === 'mobile';