# General Translation Integrations: 扩展 API
URL: https://generaltranslation.com/zh/docs/integrations/paraglide/reference/extension-api.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 自定义哪些内容被识别为 Paraglide JS、要分析哪些文件格式，以及如何解析导入语句。本页为目标、语言、打包工具配置和解析器的 API 参考。

本页所有内容均从 `@generaltranslation/paraglide-js/compiler` 导出，并通过选项参数传入 [`collectContext`](/docs/integrations/paraglide/reference/collect-context)。分析过程本身 (模块图、用法分析和渲染) 属于内部实现。

## 概览 [#overview]

| API                        | 描述                                   |
| -------------------------- | ------------------------------------ |
| [目标](#targets)             | 哪些已解析的文件属于 Paraglide JS，以及这些文件的导出内容。 |
| [语言](#languages)           | 由框架工具链转换为 TypeScript 的文件格式。          |
| [打包工具配置](#bundler-configs) | 用于读取导入别名的配置文件。                       |
| [解析器](#resolvers)          | 将导入解析为文件的函数，以及这些函数所接入的收集器。           |

## 目标 [#targets]

目标用于指定哪些已解析的文件属于 Paraglide JS，以及这些文件中各个导出分别是什么。通过 [`targets`](/docs/integrations/paraglide/reference/collect-context#targets) 选项传入目标。若有多个目标匹配同一文件，则以最后一个为准。

```ts
type ParaglideTarget = {
  name: string; // 用于标记用法的标签，例如 "message"
  matches(file: TargetFile): boolean;
  // 返回 undefined 表示不跟踪该导出。
  exportSymbol(exportName: string, file: TargetFile): SymbolSpec | undefined;
};

type TargetFile = {
  file: string; // 绝对路径，使用正斜杠
  outdir: string | undefined; // 包含该文件的输出目录
  outdirPath: string | undefined; // 相对于 outdir，例如 "messages.js"
};

type SymbolSpec =
  | { type: 'namespace'; member(name: string): SymbolSpec | undefined }
  // methods：调用时同样计入的方法，例如消息上的 .parts()
  | { type: 'value'; name: string; methods?: readonly string[] };
```

| 导出                                                | 描述                                                                                                                                                                                |
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `defaultTargets`                                  | `messagesTarget`、`runtimeTarget`、`serverTarget`、`registryTarget` 和 `adapterTargets`。                                                                                              |
| `messagesTarget`                                  | `messages.js` (含其 `m` 命名空间) 以及 `messages/` 下的所有模块。名称为 `message`。                                                                                                                  |
| `runtimeTarget`, `serverTarget`, `registryTarget` | `runtime.js`、`server.js` 和 `registry.js` 的所有导出。                                                                                                                                   |
| `adapterTargets`                                  | Paraglide 的框架适配器：`@inlang/paraglide-js-react`、`-solid`、`-svelte` 和 `-vue`，以及 Paraglide JS 1 的 `@inlang/paraglide-sveltekit`、`@inlang/paraglide-next` 和 `@inlang/paraglide-astro`。 |
| `defineTarget(target)`                            | 原样返回该目标，并将其类型标注为 `ParaglideTarget`。                                                                                                                                          |
| `generatedFileTarget(name, outdirPath)`           | 输出目录中的某个文件，追踪其所有导出。                                                                                                                                                               |
| `packageTarget(name, packageName)`                | 某个已安装的软件包，追踪其具名导出。                                                                                                                                                                |

*注意：只有 `message` 目标的用法会写入[元数据文件](/docs/integrations/paraglide/reference/metadata-files)。其他目标的用法也会被分析，但由于没有对应的消息键，因此不会写入。*

## 语言 [#languages]

语言借助框架自身的工具，将某种文件格式转换为单个 JavaScript 或 TypeScript 模块。可通过 [`languages`](/docs/integrations/paraglide/reference/collect-context#languages) 选项传入语言。 (参见[添加文件格式](/docs/integrations/paraglide/guides/adding-file-formats)。) 

```ts
type SourceLanguage = {
  name: string;
  extensions: readonly string[];
  // 认领脚本扩展名（例如 .ts 文件中的 Angular 组件）时必须提供。
  detect?(source: string, file: string): boolean;
  // 应用中需要安装的软件包；缺少某个软件包时会提示其名称。
  requires?: readonly string[];
  // 随附提供某个必需软件包的软件包：{ svelte2tsx: 'svelte-check' }。
  installedWith?: Readonly<Record<string, string>>;
  // 工具未安装时返回 undefined；工具拒绝该文件时抛出异常。
  // 无论哪种情况，该文件都会被跳过。
  generate(
    source: string,
    file: string,
    context: LanguageContext
  ): GeneratedSource | undefined | Promise<GeneratedSource | undefined>;
};

type LanguageContext = {
  // 导入应用中已安装的软件包；若未安装则为 undefined。
  load<T = unknown>(specifier: string): Promise<T | undefined>;
};

type ParseLang = 'js' | 'jsx' | 'ts' | 'tsx';
```

### 生成的源代码

`generate` 返回一个 `GeneratedSource`。没有映射的代码不会被计为一次用法。

| 字段                   | 描述                                                                                           | 类型                  | 可选 |
| -------------------- | -------------------------------------------------------------------------------------------- | ------------------- | -- |
| `code`               | 以单个模块形式表示的文件。                                                                                | `string`            | 否  |
| `lang`               | `code` 的语言。                                                                                  | `ParseLang`         | 否  |
| `mappings`           | `code` 中每个范围对应文件中的哪个位置。                                                                      | `Mapping[]`         | 否  |
| `elements`           | 文件的标记，用于为每次用法标注其所属元素。该标注不会写入元数据文件。                                                           | `SourceElement[]`   | 是  |
| `scripts`            | 文件中独立的模块，例如 Astro 页面的客户端脚本，每个均为一个 `GeneratedScript`：`{ code, lang, mappings }`。              | `GeneratedScript[]` | 是  |
| `componentFields`    | 模板未经声明即读取其字段的类，Angular 模板就是如此。每一项均为一个 `ComponentFields`：`{ specifier, className?, range? }`。 | `ComponentFields[]` | 是  |
| `scopeObjects`       | 其成员像模块内名称一样进行解析的对象，例如 Vue 的 `__VLS_ctx`。                                                     | `string[]`          | 是  |
| `props`              | 组件在何处读取调用点传入的属性：`{ calls?, members?, variables?, undeclared? }`。                             | `object`            | 是  |
| `componentInstances` | 除 JSX 外，生成的代码如何渲染导入的组件：`{ via: 'new' \| 'call', path }`。                                     | `object`            | 是  |

### 映射与元素

```ts
// 生成代码中的 [generated, generated + length) 对应
// 源代码中的 [source, source + sourceLength)。sourceLength 默认为 length。
type Mapping = {
  generated: number;
  source: number;
  length: number;
  sourceLength?: number;
};

// 基于第 3 版 source map（例如 svelte2tsx 生成的）：map 可以是对象
// （@jridgewell/trace-mapping 的 EncodedSourceMap），也可以是 JSON 字符串。
function mappingsFromSourceMap(
  map: EncodedSourceMap | string,
  generatedCode: string,
  sourceCode: string
): Mapping[];

// 基于 Volar 虚拟代码的映射：
// @vue/language-core, @mdx-js/language-service, Glint.
// 原样传入 Volar 的映射即可。
function mappingsFromVolar(
  mappings: readonly {
    sourceOffsets: readonly number[];
    generatedOffsets: readonly number[];
    lengths: readonly number[];
    generatedLengths?: readonly number[];
  }[]
): Mapping[];
```

`SourceElement` 描述单个标记元素及其在源文本中的偏移量，包含：`name`、`start`、`end`、`nameStart`、`nameEnd`、`openEnd`、`component` 和 `attributes` (每项均为 `{ name, start, end }`，其中范围对应该属性的值) 。

### 内置语言

`defaultLanguages` 依次包含：`vueLanguage`、`svelteLanguage`、`astroLanguage`、`mdxLanguage`、`markdownLanguage`、`angularComponentLanguage`、`angularTemplateLanguage`、`analogLanguage`、`markoLanguage` 和 `emberLanguage`。其中每一项也都单独导出。各语言对应的文件和工具，请参阅[支持的文件格式](/docs/integrations/paraglide/reference/file-formats)。

## 打包工具配置 [#bundler-configs]

打包工具配置可直接从配置文件中读取导入别名，无需运行打包工具。请通过 [`bundlerConfigs`](/docs/integrations/paraglide/reference/collect-context#bundler-configs) 选项传入这些配置 (参见[解析导入语句](/docs/integrations/paraglide/guides/resolving-imports#bundler-config)) 。

```ts
type BundlerConfig = {
  name: string;
  files: readonly string[]; // 可能的配置文件名
  // file 为绝对路径。若失败（无论是返回失败还是抛出异常），都会报告错误，
  // 并跳过该配置。
  read(
    file: string,
    context: ConfigContext
  ): Promise<ImportResolution | ConfigFailure>;
};

type ImportResolution = {
  aliases: readonly ImportAlias[];
  rootDirectory?: string; // 解析 /src/a.js 时所基于的目录（即 Vite 的 root）
};

type ConfigFailure = { error: string };

type ConfigContext = {
  // 从应用中导入软件包；若未安装，则返回 undefined。
  load<T = unknown>(specifier: string): Promise<T | undefined>;
};

type ImportAlias = {
  find: string | RegExp; // 字符串可匹配 find 及 find/…
  replacement: string;
  exact?: boolean; // 字符串仅匹配 find 本身（即 webpack 的 name$）
};

type AliasOption = Readonly<Record<string, string>> | readonly ImportAlias[];
```

| 导出                              | 描述                                                                                    |
| ----------------------------------- | ------------------------------------------------------------------------------------- |
| `defaultBundlerConfigs`             | 依次为 `viteConfig`、`webpackConfig` 和 `rspackConfig`。                                    |
| `viteConfig`                        | 使用应用自身的 Vite 读取 `vite.config.*`。返回解析后的别名以及 Vite 的根目录。                                 |
| `webpackConfig`, `rspackConfig`     | 导入 `webpack.config.*` 和 `rspack.config.*`，并读取其中的 `resolve.alias`。                     |
| `webpackLikeConfig(name, baseName)` | 为名为 `baseName`、扩展名为 `.js`、`.mjs`、`.ts`、`.cjs`、`.mts` 或 `.cts` 的 webpack 格式文件创建打包工具配置。 |

webpack 格式的配置可以导出一个对象、一个函数，或由其中任意一种组成的列表；若导出的是列表，则使用其第一个条目。调用函数时会传入空的 `env` 和 `{ mode: 'production' }`。

## 解析器 [#resolvers]

解析器返回某个导入语句解析到的文件，若无法解析则返回 `undefined`。如需使用自定义解析器，请自行创建由 [`collectContext`](/docs/integrations/paraglide/reference/collect-context) 包装的收集器。 (参见[解析导入语句](/docs/integrations/paraglide/guides/resolving-imports#custom-resolver)。) 

```ts
type Resolver = (
  specifier: string,
  importer: string
) => Promise<string | undefined>;

function createCollector(
  options: ParaglideContextOptions,
  environment: CollectorEnvironment
): ContextCollector;

type CollectorEnvironment = {
  root: string; // 项目，或项目中的某个目录
  logger: CollectorLogger; // { warn(message), info(message) }
  resolver: Resolver;
};
```

`ParaglideContextOptions` 包含 `collectContext` 中与解析无关的选项：`include`、`exclude`、`targets`、`languages`、`inlangProjects`、`radius`、`outdirs` 和 `autoImports`。在返回的 `ContextCollector` 上，先调用 `scanAll()` 分析项目，再调用 `write()` 写入元数据文件。

| 导出                       | 描述                                                                                                                                                                                                    |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `nodeResolver(options?)` | 无需打包工具，即可按打包工具的方式解析：支持别名、软件包的 `exports` 和 `imports`、每个导入方最近的 `tsconfig.json` 中的 `paths`，以及 TypeScript 将 `./a.js` 映射到 `./a.ts` 的规则。接受 `NodeResolverOptions`：`{ alias?, rootDirectory?, conditions? }`。 |
| `ProjectResolver`        | `collectContext` 所用的解析器：先应用打包工具配置中的别名，再交由 `nodeResolver` 处理。                                                                                                                                          |

```ts
import {
  createCollector,
  ProjectResolver,
} from '@generaltranslation/paraglide-js/compiler';

const environment = { root: process.cwd(), logger: console };
// ProjectResolverOptions：NodeResolverOptions 和 bundlerConfigs
const resolver = new ProjectResolver({ alias: { '~': '/app/src' } }, environment);

const collector = createCollector(
  { include: ['src'] },
  { ...environment, resolver: resolver.resolve }
);

await collector.scanAll();
await collector.write();
await resolver.warnUnresolved(); // 列出可能对应未声明别名的导入
```

## Sitemap

See the full [sitemap](https://generaltranslation.com/sitemap.md) for all pages.
