@fe-free/ai 4.0.5 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @fe-free/ai
2
2
 
3
+ ## 5.0.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @fe-free/core@5.0.0
9
+ - @fe-free/icons@5.0.0
10
+ - @fe-free/tool@5.0.0
11
+
3
12
  ## 4.0.5
4
13
 
5
14
  ### Patch Changes
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from 'i18next-cli';
2
+
3
+ export default defineConfig({
4
+ locales: ['zh-CN', 'en-US'],
5
+ extract: {
6
+ primaryLanguage: 'zh-CN',
7
+ secondaryLanguages: ['en-US'],
8
+ input: ['./src/**/*.{js,jsx,ts,tsx}'],
9
+ output: './src/locales/{{language}}/{{namespace}}.json',
10
+ },
11
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fe-free/ai",
3
- "version": "4.0.5",
3
+ "version": "5.0.0",
4
4
  "description": "",
5
5
  "main": "./src/index.ts",
6
6
  "author": "",
@@ -12,16 +12,21 @@
12
12
  "dependencies": {
13
13
  "ahooks": "^3.7.8",
14
14
  "classnames": "^2.5.1",
15
- "@fe-free/core": "4.0.5"
15
+ "@fe-free/core": "5.0.0"
16
16
  },
17
17
  "peerDependencies": {
18
18
  "antd": "^5.27.1",
19
19
  "dayjs": "~1.11.10",
20
+ "i18next": "^25.7.2",
21
+ "i18next-browser-languagedetector": "^8.2.0",
22
+ "i18next-icu": "^2.4.1",
20
23
  "react": "^19.2.0",
21
- "@fe-free/icons": "4.0.5",
22
- "@fe-free/tool": "4.0.5"
24
+ "react-i18next": "^16.4.0",
25
+ "@fe-free/icons": "5.0.0",
26
+ "@fe-free/tool": "5.0.0"
23
27
  },
24
28
  "scripts": {
25
- "test": "echo \"Error: no test specified\" && exit 1"
29
+ "test": "echo \"Error: no test specified\" && exit 1",
30
+ "i18n-extract": "rm -rf ./src/locales/zh-CN && npx i18next-cli extract"
26
31
  }
27
32
  }
@@ -0,0 +1,13 @@
1
+ {
2
+ "@fe-free/ai": {
3
+ "sender": {
4
+ "addFileUrl": "Add file URL",
5
+ "addImageOrFile": "Add image or file",
6
+ "aiGeneratedDisclaimer": "Content is generated by AI and cannot guarantee the accuracy of information, for reference only",
7
+ "describeYourQuestion": "Describe your question",
8
+ "dragFileHere": "Drag files here",
9
+ "exceedMaxUploadCount": "Exceeded maximum upload count {count}",
10
+ "pleaseEnterFileUrl": "Please enter file URL"
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "@fe-free/ai": {
3
+ "sender": {
4
+ "addFileUrl": "添加文件URL",
5
+ "addImageOrFile": "添加图片或文件",
6
+ "aiGeneratedDisclaimer": "内容由 AI 生成,无法确保信息的真实准确,仅供参考",
7
+ "describeYourQuestion": "描述你的问题",
8
+ "dragFileHere": "在此处拖放文件",
9
+ "exceedMaxUploadCount": "超过最大上传数量{count}",
10
+ "pleaseEnterFileUrl": "请输入文件URL"
11
+ }
12
+ }
13
+ }
@@ -4,6 +4,7 @@ import type { UploadFile } from 'antd';
4
4
  import { App, Button, Dropdown, Input, Modal, Upload } from 'antd';
5
5
  import type { RefObject } from 'react';
6
6
  import { useState } from 'react';
7
+ import { useTranslation } from 'react-i18next';
7
8
  import FilesIcon from '../svgs/files.svg?react';
8
9
  import type { SenderProps } from './types';
9
10
 
@@ -18,6 +19,7 @@ function FileAction(
18
19
  const { filesMaxCount } = allowUpload || {};
19
20
 
20
21
  const { message } = App.useApp();
22
+ const { t } = useTranslation();
21
23
 
22
24
  const [url, setUrl] = useState<string>('');
23
25
  const [open, setOpen] = useState<boolean>(false);
@@ -31,7 +33,7 @@ function FileAction(
31
33
  items: [
32
34
  {
33
35
  key: 'add-file',
34
- label: '添加图片或文件',
36
+ label: t('@fe-free/ai.sender.addImageOrFile', '添加图片或文件'),
35
37
  icon: <Icons component={FilesIcon} />,
36
38
  onClick: () => {
37
39
  refUpload.current?.click();
@@ -39,7 +41,7 @@ function FileAction(
39
41
  },
40
42
  {
41
43
  key: 'add-file-url',
42
- label: '添加文件URL',
44
+ label: t('@fe-free/ai.sender.addFileUrl', '添加文件URL'),
43
45
  icon: <Icons component={LinkOutlined} />,
44
46
  onClick: () => {
45
47
  setUrl('');
@@ -54,12 +56,16 @@ function FileAction(
54
56
  </Dropdown>
55
57
  {open && (
56
58
  <Modal
57
- title="添加文件URL"
59
+ title={t('@fe-free/ai.sender.addFileUrl', '添加文件URL')}
58
60
  open
59
61
  onCancel={() => setOpen(false)}
60
62
  onOk={() => {
61
63
  if (filesMaxCount && value?.files && value.files.length >= filesMaxCount) {
62
- message.warning(`超过最大上传数量${filesMaxCount}`);
64
+ message.warning(
65
+ t('@fe-free/ai.sender.exceedMaxUploadCount', '超过最大上传数量{count}', {
66
+ count: filesMaxCount,
67
+ }),
68
+ );
63
69
  return;
64
70
  }
65
71
 
@@ -70,7 +76,7 @@ function FileAction(
70
76
  }}
71
77
  >
72
78
  <Input.TextArea
73
- placeholder="请输入文件URL"
79
+ placeholder={t('@fe-free/ai.sender.pleaseEnterFileUrl', '请输入文件URL')}
74
80
  value={url}
75
81
  onChange={(e) => setUrl(e.target.value)}
76
82
  />
@@ -92,6 +98,7 @@ function FileUpload(
92
98
  const { uploadAction, filesMaxCount } = allowUpload || {};
93
99
 
94
100
  const { message } = App.useApp();
101
+ const { t } = useTranslation();
95
102
 
96
103
  return (
97
104
  <Upload.Dragger
@@ -102,7 +109,11 @@ function FileUpload(
102
109
  maxCount={uploadMaxCount ? uploadMaxCount + 1 : undefined}
103
110
  onChange={(info) => {
104
111
  if (uploadMaxCount && info.fileList.length > uploadMaxCount) {
105
- message.warning(`超过最大上传数量${filesMaxCount}`);
112
+ message.warning(
113
+ t('@fe-free/ai.sender.exceedMaxUploadCount', '超过最大上传数量{count}', {
114
+ count: filesMaxCount,
115
+ }),
116
+ );
106
117
 
107
118
  setFileList(info.fileList.slice(-uploadMaxCount));
108
119
  return;
@@ -111,7 +122,7 @@ function FileUpload(
111
122
  setFileList(info.fileList);
112
123
  }}
113
124
  >
114
- <div ref={refUpload}>在此处拖放文件</div>
125
+ <div ref={refUpload}>{t('@fe-free/ai.sender.dragFileHere', '在此处拖放文件')}</div>
115
126
  </Upload.Dragger>
116
127
  );
117
128
  }
@@ -4,6 +4,7 @@ import type { UploadFile } from 'antd/lib';
4
4
  import classNames from 'classnames';
5
5
  import type { RefObject } from 'react';
6
6
  import { useCallback, useMemo, useRef, useState } from 'react';
7
+ import { useTranslation } from 'react-i18next';
7
8
  import { Actions } from './actions';
8
9
  import { FileUpload, Files } from './files';
9
10
  import './style.scss';
@@ -27,17 +28,15 @@ function Text(props: SenderProps & { refText: RefObject<HTMLTextAreaElement> })
27
28
  );
28
29
  }
29
30
 
30
- const defaultProps = {
31
- placeholder: '描述你的问题',
32
- };
33
-
34
31
  function Sender(originProps: SenderProps) {
32
+ const { t } = useTranslation();
35
33
  const props = useMemo(() => {
36
34
  return {
37
- ...defaultProps,
35
+ placeholder:
36
+ originProps.placeholder ?? t('@fe-free/ai.sender.describeYourQuestion', '描述你的问题'),
38
37
  ...originProps,
39
38
  };
40
- }, [originProps]);
39
+ }, [originProps, t]);
41
40
 
42
41
  const refText = useRef<HTMLTextAreaElement>(null);
43
42
 
@@ -136,7 +135,10 @@ function Sender(originProps: SenderProps) {
136
135
  />
137
136
  </div>
138
137
  <div className="mt-1 text-center text-xs text-03">
139
- 内容由 AI 生成,无法确保信息的真实准确,仅供参考
138
+ {t(
139
+ '@fe-free/ai.sender.aiGeneratedDisclaimer',
140
+ '内容由 AI 生成,无法确保信息的真实准确,仅供参考',
141
+ )}
140
142
  </div>
141
143
  </div>
142
144
  );
package/src/tip.tsx CHANGED
@@ -1,5 +1,15 @@
1
+ import { useTranslation } from 'react-i18next';
2
+
1
3
  function Tip() {
2
- return <div className="test-xs text-01">内容由 AI 生成,无法确保信息的真实准确,仅供参考</div>;
4
+ const { t } = useTranslation();
5
+ return (
6
+ <div className="test-xs text-01">
7
+ {t(
8
+ '@fe-free/ai.sender.aiGeneratedDisclaimer',
9
+ '内容由 AI 生成,无法确保信息的真实准确,仅供参考',
10
+ )}
11
+ </div>
12
+ );
3
13
  }
4
14
 
5
15
  export { Tip };