Skip to content

添加新字典

本文介绍如何为 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 中:

  1. 导入图标:
ts
import yourDictIcon from './yourDict/icon.png';
  1. 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 或自定义选项:

  1. yourDict/types.ts 中定义配置类型和默认值
  2. utils/storage.ts 中添加 storage 定义
  3. 创建 yourDict/configView.tsx 构建配置界面
  4. 如果配置需要参与备份/恢复,创建 yourDict/settingBackup.ts 并导出 settingsBackupHandler

添加国际化(可选)

如果模块名称或配置文案需要翻译,在 i18n/locales/ 下的每个语言文件中添加对应条目:

json
{
  "dict.yourDict": "你的词典"
}

优秀参考

需求参考模块
简单翻译器google/
带配置的翻译器caiyun/deeplx/
结构化词典urban/jisho/
自定义 HTML 视图bing/
带设置页面的词典wiktionary/
AI 输出openai/