添加新字典
本文介绍如何为 ClueLens 添加新的词典或翻译模块。所有词典模块位于 components/dicts/ 目录下。
核心概念
每个词典模块由以下文件组成(按需添加):
| 文件 | 作用 | 必须 |
|---|---|---|
search.ts | 执行查询,返回结果数据 | ✅ |
view.tsx | 渲染查询结果的 React 组件 | ✅ |
types.ts | 结果数据的类型定义 | 结构化词典需要 |
configView.tsx | 词典配置界面 | 需要配置时 |
settingBackup.ts | 设置备份/恢复处理 | 需要配置时 |
icon.png | 词典图标 | ✅ |
两种模式
简单翻译器
适用于返回翻译文本的服务(如 Google 翻译、彩云小译、DeepLx)。
search.ts返回string[]view.tsx复用共享组件CommonView- 参考实现:
google/、caiyun/、deeplx/
结构化词典
适用于返回结构化数据的词典(如 Bing 词典、Jisho、Urban Dictionary)。
search.ts返回自定义类型数组- 需要
types.ts定义数据结构 - 需要自定义
view.tsx渲染组件 - 参考实现:
bing/、jisho/、urban/、wiktionary/
五步流程
第一步:注册 DictID
在 components/dicts/types.ts 中添加新的枚举值:
ts
export enum DictID {
// ... 已有的
YourDict = 'yourDict',
}第二步:创建模块文件夹
components/dicts/yourDict/
├── icon.png # 词典图标
├── search.ts # 搜索逻辑
├── view.tsx # 结果渲染
├── types.ts # (可选)类型定义
├── configView.tsx # (可选)配置界面
└── settingBackup.ts # (可选)备份处理第三步:实现 search.ts
模块必须导出一个 search 函数,返回数组。
简单翻译器示例:
ts
import { SearchOptions } from '../types';
export async function search(
text: string,
options?: SearchOptions
): Promise<string[]> {
const query = text.trim();
if (!query) return [];
// 调用翻译 API
const translatedText = await callYourAPI(query, options?.targetLang);
return translatedText ? [translatedText] : [];
}结构化词典示例:
ts
import { YourDictResult } from './types';
export async function search(text: string): Promise<YourDictResult[]> {
const query = text.trim();
if (!query) return [];
// 调用词典 API 或解析网页
const results = await fetchResults(query);
return results;
}要点
- 始终调用
trim()处理输入 - 空输入返回
[] - 翻译器可使用
options?.targetLang获取用户设置的目标语言 - 将网络请求逻辑保留在
search.ts中
第四步:实现渲染组件
简单翻译器——复用 CommonView:
tsx
import TranslateView from '../shared/CommonView';
export function ResultsView({ data }: { data: unknown[] }) {
return <TranslateView result={data as string[]} />;
}结构化词典——自定义视图:
tsx
import { YourDictResult } from './types';
export function ResultsView({ data }: { data: unknown[] }) {
const results = data as YourDictResult[];
return (
<div>
{results.map((item, i) => (
<div key={i}>
<h3>{item.title}</h3>
<p>{item.definition}</p>
</div>
))}
</div>
);
}重要
view.tsx 必须导出名为 ResultsView 的具名组件(不是默认导出)。
第五步:注册元数据
在 components/dicts/index.tsx 中:
- 导入图标:
ts
import yourDictIcon from './yourDict/icon.png';- 在
dictMetaMap中添加条目:
ts
[DictID.YourDict]: {
id: DictID.YourDict,
displayName: 'Your Dictionary',
displayNameKey: 'dict.yourDict',
icon: yourDictIcon,
language: { type: 'all' }, // 或 monolingual / pairs
type: ModuleType.Dict, // 或 Translator / Other
},language 字段说明:
| 类型 | 含义 | 示例 |
|---|---|---|
{ type: 'all' } | 支持所有语言 | Google 翻译 |
{ type: 'monolingual', languages: ['en'] } | 仅支持特定语言 | DictionaryAPI |
{ type: 'pairs', pairs: [['en', 'zh'], ['zh', 'en']] } | 支持语言对 | Bing 词典 |
type 字段说明:
| 类型 | 含义 | 效果 |
|---|---|---|
ModuleType.Dict | 词典 | 不传递 targetLang |
ModuleType.Translator | 翻译器 | 自动传递 targetLang |
ModuleType.Other | 其他(如 AI) | 不传递 targetLang |
搜索模块和渲染组件通过文件名自动发现(import.meta.glob),无需手动注册。
添加配置项(可选)
如果模块需要 API Key 或自定义选项:
- 在
yourDict/types.ts中定义配置类型和默认值 - 在
utils/storage.ts中添加 storage 定义 - 创建
yourDict/configView.tsx构建配置界面 - 如果配置需要参与备份/恢复,创建
yourDict/settingBackup.ts并导出settingsBackupHandler
添加国际化(可选)
如果模块名称或配置文案需要翻译,在 i18n/locales/ 下的每个语言文件中添加对应条目:
json
{
"dict.yourDict": "你的词典"
}优秀参考
| 需求 | 参考模块 |
|---|---|
| 简单翻译器 | google/ |
| 带配置的翻译器 | caiyun/、deeplx/ |
| 结构化词典 | urban/、jisho/ |
| 自定义 HTML 视图 | bing/ |
| 带设置页面的词典 | wiktionary/ |
| AI 输出 | openai/ |