---
title: 插件本地化 SDK
description: 面向插件的权限门控主机语言、localized text 与隔离 Domain Lexicon API
---

# 插件本地化 SDK

## 概述

Localization SDK 是插件读取主机语言、解析本地化值、创建可跨 transport 传递的 i18n 消息，以及使用宿主 Domain Lexicon 的正式合同。

`sdkapi >= 260713` 的插件可从以下入口使用：

- 主进程 / runtime context：`context.utils.i18n` 与 `context.utils.lexicon`
- 主进程镜像：`context.utils.plugin.i18n` 与 `context.utils.plugin.lexicon`
- 插件 renderer：从 `@talex-touch/utils/plugin/sdk` 导入 `usePluginI18n()` 与 `usePluginLexicon()`

当前主机语言为 `en-US` 与 `zh-CN`。

## Manifest 要求

只声明插件实际使用的权限：

:::TuffCodeBlock{lang="json"}
---
code: |
  {
  "sdkapi": 260713,
  "permissions": {
  "required": ["i18n.read", "lexicon.read"],
  "optional": ["lexicon.register"]
  },
  "permissionReasons": {
  "i18n.read": "按主机语言解析插件文案",
  "lexicon.read": "查询宿主领域词库",
  "lexicon.register": "在插件启用期间注册插件私有别名"
  }
  }
---
:::

| 权限               | 对应方法                       |
| ------------------ | ------------------------------ |
| `i18n.read`        | `getLocale()`、`resolveText()` |
| `lexicon.read`     | `resolve()`、`search()`        |
| `lexicon.register` | `register()`                   |

宿主会同时校验 SDK marker、manifest 声明、当前 grant、插件已加载状态和 verified plugin identity。任一条件缺失都会在 locale / lexicon 服务执行前 fail-closed。

`createMessage()` 只是纯字符串构造，不读取主机状态；空 key 会被拒绝。

## Runtime 用法

:::TuffCodeBlock{lang="typescript"}
---
code: |
  export default {
  async onInit(context) {
  const { i18n, lexicon } = context.utils

        const locale = await i18n.getLocale()
        const title = await i18n.resolveText(
          {
            default: 'Unit Converter',
            locales: { 'zh-CN': '单位换算' }
          },
          locale
        )
        const message = i18n.createMessage('plugin.ready', { title })

        const meter = await lexicon.resolve('unit.length.meter', {
          locale,
          domain: 'unit'
        })
        const matches = await lexicon.search('米', {
          locale,
          domain: 'unit',
          limit: 5
        })

        context.utils.logger.info(
          `${message}:${meter?.label ?? 'missing'}:${matches.length}`
        )
      }

  ## }
---
:::

## Renderer 用法

:::TuffCodeBlock{lang="typescript"}
---
code: |
  import {
  usePluginI18n,
  usePluginLexicon
  } from '@talex-touch/utils/plugin/sdk'

  const i18n = usePluginI18n()
  const lexicon = usePluginLexicon()

  const locale = await i18n.getLocale()
  const label = await i18n.resolveText({
  default: 'Ready',
  locales: { 'zh-CN': '就绪' }
  })
  const capabilities = await lexicon.search('就绪', {
  locale,
  domain: 'capability'
  })
---
:::

Renderer hooks 需要已建立的插件 renderer channel。不要在普通应用 renderer 中调用，也不要在插件 channel ready 前调用。

## API 参考

### I18n

| 方法                          | 返回值                        | 说明                                                                |
| ----------------------------- | ----------------------------- | ------------------------------------------------------------------- |
| `getLocale()`                 | `Promise<'en-US' \| 'zh-CN'>` | 读取当前主机语言。                                                  |
| `resolveText(value, locale?)` | `Promise<string>`             | 解析字符串或 `{ default, locales }`；省略 `locale` 时使用主机语言。 |
| `createMessage(key, params?)` | `string`                      | 不调用宿主，创建 `$i18n:` transport message。                       |

### Domain Lexicon

| 方法                          | 返回值                                        | 说明                                                                        |
| ----------------------------- | --------------------------------------------- | --------------------------------------------------------------------------- |
| `resolve(id, options?)`       | `Promise<ResolvedDomainLexiconEntry \| null>` | 解析 official entry 或调用插件自己注册的 entry。                            |
| `search(query, options?)`     | `Promise<DomainLexiconMatch[]>`               | 搜索 official 与调用插件私有 entry；支持 `locale`、`domain`、`limit`。      |
| `register(entries, options?)` | `Promise<PluginLexiconRegisterResult>`        | 原子注册 plugin-local entries；`replace: true` 会替换调用插件当前 overlay。 |

支持的 domain：`unit`、`currency`、`timezone`、`capability`、`fileType`、`systemAction`。

## 注册插件私有词条

:::TuffCodeBlock{lang="typescript"}
---
code: |
  const result = await context.utils.lexicon.register(
  [
  {
  id: 'status.ready',
  domain: 'capability',
  version: '1',
  labels: {
  default: 'Ready',
  locales: { 'zh-CN': '就绪' }
  },
  aliases: {
  default: ['ready'],
  locales: { 'zh-CN': ['就绪'] }
  }
  }
  ],
  { replace: false }
  )

  // 宿主分配 plugin:<pluginId>:status.ready。
  console.log(result.ids[0])
---
:::

注册边界：

- 插件只提交 local id，不能选择其他插件 namespace。
- 宿主把 `status.ready` 投影为 `plugin:<pluginId>:status.ready`，并设置 `source=plugin:<pluginId>`。
- 插件不能覆盖 official id，也不能 resolve/search 其他插件的 overlay。
- 每插件最多 100 entries；单次请求最多 50 entries / 256 KiB。
- 批次先完整验证，再原子提交。
- 插件 overlay 只驻留内存；disable/unload 时清理，不写入 SQLite、Catalog 或同步载荷。

## 错误与恢复

权限、SDK、identity 与 payload 失败都会返回显式 transport error。调用方应把它们展示为 capability unavailable/degraded，而不是伪造本地化值或返回“成功但为空”。

常见错误码：

- `PLUGIN_I18N_PERMISSION_UNAVAILABLE`
- `PLUGIN_I18N_PERMISSION_DENIED`
- `PLUGIN_LEXICON_PERMISSION_UNAVAILABLE`
- `PLUGIN_LEXICON_PERMISSION_DENIED`
- `PLUGIN_LOCALIZATION_SDK_UNSUPPORTED`
- `PLUGIN_LOCALIZATION_INVALID_REQUEST`
- `PLUGIN_LOCALIZATION_PLUGIN_UNAVAILABLE`

## 不要把宿主内部接口当成插件 API

`i18nResolver.addMessages()` 与直接导入宿主 locale registry 都是应用内部机制，不提供插件 identity、permission、namespace 隔离或 lifecycle cleanup。插件必须使用本页 Localization SDK。

## 相关文档

- [Plugin Context](./plugin-context.zh.mdc)
- [Permission SDK](./permission.zh.mdc)
- [Manifest 参考](../reference/manifest.zh.mdc)
- [Intelligence SDK](./intelligence.zh.mdc)
