# @codaco/app-i18n 中文文档

规范地址：https://npmcn.com/package/%40codaco/app-i18n/

版本：0\.3\.0
npm 元数据更新时间：2026-10-13T12:13:07.943Z
中文译文更新时间：2026-11-10T06:29:56.971Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40codaco/app-i18n
原文对照：https://npmcn.com/package/%40codaco/app-i18n/?lang=original
源码仓库：https://github.com/complexdatacollective/network-canvas-monorepo

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：122 kB，42 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：6 个
- peer 依赖：react ^19\.3\.0
- 首次发布：2026-09-09T20:48:40.636Z
- 最新版本发布：2026-10-13T12:13:07.608Z
- 近 30 天下载量：3553（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：3（近 12 个月 3 个）

## 中文简介

网络Canvas应用程序共享应用程序UI国际化:ICU消息目录,地语谈判,和React绑定.

## 安装

```sh
npm install @codaco/app-i18n
```

也可以使用：`pnpm add @codaco/app-i18n`、`yarn add @codaco/app-i18n`、`bun add @codaco/app-i18n`

## README

# 应用程序 UI 本地化

`@codaco/app-i18n` 支持的网络国际化外观 Canvas应用铬. 议定书授权的内容、收集的数据和 持续识别器保留自己的语言和身份.

## 信件和目录

导入 `defineMessages`, (中文(简体) ), `defineMessage`, (中文(简体) ), `createAppIntl`及其类型 `@codaco/app-i18n/messages`。本条目在 React 服务器组件和 普通 JavaScript 语境 。 使用 `useAppIntl` 在客户端组件中; 它使 没有安装提供者时的英语默认值 .

给每个描述符一个稳定的名字空间,一个英文 `defaultMessage`,以及 向翻译解释背景的描述。 保持句子完整; 使用 ICU 复数/ 选择、 富文本标记和数字/ 日期参数而不是 加入已翻译的碎片.

```tsx
import { defineMessages } from '@codaco/app-i18n/messages';
import { useAppIntl } from '@codaco/app-i18n/react';

const messages = defineMessages({
  selected: {
    id: 'example.records.selected',
    defaultMessage:
      '{count, plural, one {# record selected} other {# records selected}}',
    description: 'Selection count above the researcher records table.',
  },
});

function SelectedCount({ count }: { count: number }) {
  return useAppIntl().formatMessage(messages.selected, { count });
}
```

主机装入目录 `common`每个被消耗的包装 和自己的应用, 一次使用一个地方(参见 [正在装入目录](https://npmcn.com/package/%40codaco/app-i18n/#readme-loading-catalogs)) (中文(简体) ). 每个地方 内 `ecosystemLocales` 每个共享目录中有完整的目录 软件包,但 `en-GB`,这是一个稀有的经过审查的英语功能。 联合国 `src/locales/en.json` 文件是生成的提取文物,从不运行时间 导入: 描述符默认提供英语运行时间倒计时。 保留 应用程序目录 `src/locales/<canonical-BCP-47-tag>.json` 页:1 构建时间汇编.

一个应用程序声明它实际支持的子集; 在其中添加一个地块 生态系统不需要其他应用程序来做广告. `defineAppLocales` 仅在明确启用时才添加诊断伪地. 不要坚持 作为生产选择的诊断选择.

使用 `AppMessage` 从 `@codaco/app-i18n/react` 用于队列对话框或土司 :

```tsx
<AppMessage message={messages.selected} values={{ count }} />
```

节点即使排入队列也订阅到活动提供者. 当操作开始冻结旧语言时格式化为字符串. Fresco UI 对话框标题、描述、动作标签和 `describeError` 调用符接受这些节点.

对于现有的仅字符串错误/结果合同, `createMessageError` 从 `@codaco/app-i18n/messages` 保存一个简单文字描述符及其命名值 不捕捉活动区域。 它保留源默认并编译 ICU AST(重症监护室). Fresco UI 已有的字段/窗体出错渲染器解析这些消息 在语言切换时显示时间并保存服务器拒绝。 使用 `AppErrorMessage` 从 `@codaco/app-i18n/react` 用于存储的其他字符串错误,或 `formatMessageError(error, intl) ?? error` 在字符串渲染器中。 普通类 审定/诊断文本保持不变。 运输清单用途 `{ dependencies: { list: dependencyIds } }`,因此组合格式化为 读者的语言 而不是切换前的捕捉.

当整个信件包含单独拥有的被翻译的标签时,通过 `{ rule: { messageError: createMessageError(ruleDescriptor) } }`清单项目 还接受这个清晰的包装。 普通的字符串总是字面数据, 即使它们恰好像一个编码错误。 此保存共享规则名称 和无名属性标签反应,而不重复其翻译.

## 正在装入目录

每个拥有目录的软件包都会导出装入器的地图:每个地方都有它 翻译,一个函数返回 `import('./<tag>.json')`。每种语言都是 因此,它自己的块,一个主机只下载它所下载的块。 联合国 没有装货机 也不需要.

| 软件包 | 条目 | 导出 |
| --- | --- | --- |
| `@codaco/app-i18n` | `@codaco/app-i18n/common` | `commonCatalogLoaders` |
| `@codaco/fresco-ui` | `@codaco/fresco-ui/locales` | `frescoUiCatalogLoaders` |
| `@codaco/interview` | `@codaco/interview/locales` | `interviewCatalogLoaders` |
| `@codaco/network-exporters` | `@codaco/network-exporters/locales` | `networkExporterCatalogLoaders` |
| `@codaco/protocol-builder` | `@codaco/protocol-builder/locales` | `protocolBuilderCatalogLoaders` |
| `@codaco/protocol-utilities` | `@codaco/protocol-utilities/locales` | `protocolUtilitiesCatalogLoaders` |
| `@codaco/protocol-validation` | `@codaco/protocol-validation/locales` | `protocolValidationCatalogLoaders` |

一个主机以同样的形状宣布自己的装载器,并传递它的一切 改为: `createCatalogSource` 从 `@codaco/app-i18n/locales`,按合并顺序排列: 常见的先是共享软件包,然后是应用程序. 后来加载器在共享上获胜 身份证.

```ts
import { commonCatalogLoaders } from '@codaco/app-i18n/common';
import {
  createCatalogSource,
  type CatalogLoaders,
} from '@codaco/app-i18n/locales';
import { frescoUiCatalogLoaders } from '@codaco/fresco-ui/locales';

const appCatalogLoaders: CatalogLoaders = {
  'es': () => import('./es.json'),
  'zh-Hans': () => import('./zh-Hans.json'),
};

export const catalogSource = createCatalogSource(
  commonCatalogLoaders,
  frescoUiCatalogLoaders,
  appCatalogLoaders,
);
```

来源一次合并并缓存一个地块 :

-   `load(locale)` 决定合并目录。 同时和重复的电话 共享一个请求,在负载失败后启动新请求.
-   `attempt(locale)` 返回该地块已有的负载,包括其 上次失败的尝试, 并且只有在没有尝试时才开始一次。 挂起这个 而不是说 `load`: 暂停使用 `load` 将开始一个新的 每次重试一次 都不要和解 A 类 `load` 尝试 在飞行中加入时作为尝试。 之前失败的 任何加入的尝试(如第一次渲染前的预装)都不可交付 因此,第一次尝试 之后仍然尝试新的.
-   `peek(locale)` 返回已装入的合并目录, 否则 `undefined`。没有软件包翻译的地块(英语,伪地块)是 总是准备好一个空目录.
-   `subscribe(onLoad)` 返回未订阅的选项.

`useLocaleCatalog(source, locale, preloaded?)` 从 `@codaco/app-i18n/react` 返回时 `{ locale, messages, failure }` 给予 `AppI18nProvider`通过它 以结果代替请求的地块, 因为两者不同, 而开关 正在装入,当装入失败时:

```tsx
import { AppI18nProvider, useLocaleCatalog } from '@codaco/app-i18n/react';
import type { ReactNode } from 'react';

import { appLocales } from './locales';
import { catalogSource } from './locales/catalogs';

export function I18n({
  locale,
  children,
}: {
  locale: string;
  children: ReactNode;
}) {
  const rendered = useLocaleCatalog(catalogSource, locale);
  return (
    <AppI18nProvider
      locale={rendered.locale}
      locales={appLocales}
      messages={rendered.messages}
      loadFailure={rendered.failure}
    >
      {children}
    </AppI18nProvider>
  );
}
```

钩子将当前语言保留在屏幕上,直到新语言装入, 然后在一次渲染中改变 所以开关从不通过英语或者 显示半翻译界面。 屏幕上什么都没有 也没有 要保留的语言, 因此第一个负载暂停: 使提供者处于 暂停边界, 或等待 `source.load(locale)` 在第一次变身之前 从不暂停.

永不停息界面的负载 。 开关留在当前 语言,第一个负载返回到英语,每个描述符 携带。 无论哪种方式,钩子都返回它无法装入的语言 `failure`,并不断尝试: 当设备回到网上, 在每次失败都加倍的等待之后 最多30秒 A 类 为页面寿命保留失败模块导入的浏览器, 如 Chrome 做,没有请求就回答失败的每一个重复,所以 在那里,语言只有在重新装入后才到达。 给 `failure` 通知提供者 作为 `loadFailure`,并告诉用户: `useLocaleLoadFailure()` 返回时 无法加载的语言的登记条目(`locale`)和 一个放在屏幕上`shown`),与 `error`,以及 `LocaleLoadFailureToast` 从 `@codaco/fresco-ui` 把它当作一个祝酒词,直到它被解职或 语言到达.

服务器主机加载请求的目录,格式,并发送相同的 向客户端发送信息作为道具。 把他们当成钩子 `preloaded` 参数 在不下载的情况下制作该语言的水合物和水合物,持续时间最长 `preloaded.locale` 匹配 `locale`数字 :

```tsx
// On the server, per request:
const messages = await catalogSource.load(locale);
const intl = createAppIntl({ locale, messages });

// In the client provider, with `messages` received as a prop:
const rendered = useLocaleCatalog(catalogSource, locale, { locale, messages });
```

在不需要资源的地方, 如一次性服务器, 一个故事书 装潢或测试, `loadCatalog(locale, ...loaders)` 从 `@codaco/app-i18n/locales` 装入并合并一个单一区域 :

```ts
import { commonCatalogLoaders } from '@codaco/app-i18n/common';
import { loadCatalog } from '@codaco/app-i18n/locales';
import { frescoUiCatalogLoaders } from '@codaco/fresco-ui/locales';

const messages = await loadCatalog(
  'es',
  commonCatalogLoaders,
  frescoUiCatalogLoaders,
);
```

装填器不带电源就导入JSON `import` 属性, 所以目录负载 只能通过捆绑机;节点自己的无害环境管理装载机无法读取. 软件包或应用程序 拥有目录的人声称 `src/locales/<tag>.json` 有一个 装入器装入它,没有装入器在缺少的文件上点出 `checkCatalogLoaders(localesDir, loaders)` 从 `@codaco/app-i18n/catalog-guards`。 。 。 . 它解决了一系列问题,当装入器正常时会空出.

## 东道国的责任

挂载 `AppI18nProvider` 与活动区域、所支持的注册和 locale 来自目录来源的消息 。 内容 `onLocaleChange` 召回代表 (一) 东道方的持久性; `null` 意思是自动谈判. `resolveAppLocale` 手柄卡通化, 最适合的浏览器匹配, 和明确的英文倒置 。 中国的请求 由脚本匹配,所以 `zh-TW`, (中文(简体) ), `zh-HK` 财务报告和审定财务报表 `zh-MO` 选择 `zh-Hant` 财务报告和审定财务报表 `zh`, (中文(简体) ), `zh-CN` 财务报告和审定财务报表 `zh-SG` 选择 `zh-Hans`,即使一个通用 `zh` 随行 浏览器列表中的区域标记 。 HTTP 主机可以获取所请求的标记 使用 `parseAcceptLanguage` 从根 `@codaco/protocol-validation` 输出.

外部提供者管理文档 `lang` 财务报告和审定财务报表 `dir`嵌入式参与者 采访或预览有一个独立的提供者,其地址是: `manageDocument={false}` 及其自身的要素 `lang` 财务报告和审定财务报表 `dir`。保留当前协议 runtime语言独立于研究者偏好.

服务器主机先解决请求的账户/ 设备/ 浏览器偏好 渲染,然后将初始化序列化给客户端. 创建每个服务器 用于与 `createAppIntl`,通过目录 `source.load(locale)`; 不将特定请求的本地状态放入 模块全局或跨用户缓存。 使用相同的明示 `timeZone` 两者 用于确定日期/时间水分的服务器格式和客户端提供者.

## Vite 构建

地点 `appI18n()` 从 `@codaco/app-i18n/vite` 在框架插件之前。 这个 编译源默认和导入到 ICU 的本地目录并删除 生产应用程序中的运行时间解析器构建。 一个出版的软件包 拥有描述符/目录使用 `appI18n({ build: 'library' })` 来编译它们 并让其消费者选择解析器.

## 下一个带涡轮包的J

使用 `@codaco/app-i18n/next-loader` 用于源默认和源语言目录. 共享加载器应用与 Vite 相同的编译器并保存客户端 指令。 。 。 源码规则保留了原扩展名, 所以下个仍然 进行其正常的TypeScript/JSX变换;只有JSON规则出JavaScript.

```ts
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  turbopack: {
    rules: {
      '*.{js,jsx,ts,tsx}': {
        condition: { not: 'foreign' },
        loaders: ['@codaco/app-i18n/next-loader'],
      },
      '**/src/locales/*.json': {
        condition: { not: 'foreign' },
        loaders: ['@codaco/app-i18n/next-loader'],
        as: '*.js',
      },
    },
    resolveAlias: {
      ...(process.env.NODE_ENV === 'production'
        ? {
            '@formatjs/icu-messageformat-parser':
              '@formatjs/icu-messageformat-parser/no-parser.js',
          }
        : {}),
    },
  },
};

export default nextConfig;
```

工作空间包导出源, 因此规则也会编译其描述符 和目录。 已发布软件包导出预编译 `dist` 文物和必须 在库建过程中编译自己的消息. 一个非目录 JSON 文件 仍然是普通数据。 不另名运行时解析器, 除非每个来源 编译默认和运行时间目录.

## 审定和生成指导

没有框架的工人/CLI诊断方法保持不变。 研究员 主机可以通过自有软件包选择本地化的演示文稿 :

-   `@codaco/protocol-validation/messages`: 协议文件错误描述符, 验证规则标签、可诉矛盾摘要和 `formatMigrationNotes(version, notes, intl)` 用于移民审批指南. 已知的迁移版本, 翻译每个完整的 Markdown 句号同时 保存列表结构和字面协议默认;未知版本 保留他们提供的笔记。 核心移徙说明仍是英文.
-   `@codaco/protocol-utilities/messages`: 选择生成冲突指导 (d) 原有技术诊断.
-   `@codaco/network-exporters/messages`: 选择导出进度描述符 由稳定的事件阶段标识.
-   `@codaco/protocol-builder`: 本地化的舞台界面显示名称, 保存 持续的协议命名独立于活动区域.

每个软件包通过其翻译提供翻译 `./locales` 输出。 这个 验证/用户/出口商中的信息和地址条目可选 `@codaco/app-i18n` 端点;其现有的引擎切入点不获取 反应依赖。 选择本地化演示文稿的主机安装端点和 添加软件包的目录加载器( 列在 [正在装入目录](https://npmcn.com/package/%40codaco/app-i18n/#readme-loading-catalogs)他们的目录来源.

## 翻译来源

更改英文句子使其翻译无效。 每个本地目录 有一份英文的忠实记录 它的录入来自一个兄弟 `src/locales/<tag>.source.json`和目录的守卫失败 当一个记录 句子已经不再匹配今天的 `en.json`。 。 。 .

没有它,一个重写英文字符串 留下每一个翻译说老 与每一个其他的守卫 仍然绿色:目录是完整的, ICU 参数仍然匹配,无一是空白的,错误的拷贝在屏幕上。 这个 而非假设 协议在英语更改后被下载,以表示否 文件是写出来的.

因此,当翻译背后的英语变化时:

1.  `pnpm --filter <pkg> i18n:extract` 重新生成 `en.json`和警卫 以 ID 开始失败, 它从英文译出 它现在说, 和翻译本身.
2.  从这三句里决定 大多数英语编辑是 社论——大写,逗号,同义词——译名还原 说对了 有些改变意义,翻译必须 在它回到读者面前之前重写.
3.  `pnpm --filter <pkg> i18n:stamp` 重写记录并打印每对 它接受了。 阅读该报告,并在重新翻译的同时予以执行; 副车厢是可审查的被接受的记录.

从磁盘中读取这些文件; 从不导入 。 所以英国人才会这样 复制出捆绑, 名称会备份它: 地方标记不能包含 点, 因此扫描本地目录的构建步骤不会出错 `es.source.json` 为目录.

只有 `defaultMessage` 记录,而不是 `description`。描述是 其编辑原因并不改变 将两人连成一对 将守卫解雇 澄清并训练人们不读就重新加印 习惯会让这个警卫一文不值.

## 核查

运行每个所有者 `i18n:extract` 脚本并输入生成的英文目录 . 编目警卫检查新鲜度 身份证 翻译描述 完整 西班牙语、英国英语、有效伊斯兰法院联盟、占位符/丰富文本等同 每一个忠实的目录都有一个装入器,每个翻译 仍然记录着它用英文做的. 此外,还审计了JSX以外的表面和复制品: 目录无法找到从未被提取的字符串 。 锻炼生产 构建、活的地盘变化、主机偏好持续以及独立 审查翻译的含义和布局.

## 常见问题

### @codaco/app-i18n 是什么？

网络Canvas应用程序共享应用程序UI国际化:ICU消息目录,地语谈判,和React绑定\.

### 如何安装 @codaco/app-i18n？

在项目目录运行 npm install @codaco/app-i18n，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：react（^19\.3\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @codaco/app-i18n 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @codaco/app-i18n 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @codaco/app-i18n 可以商用吗？

@codaco/app-i18n 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @codaco/app-i18n 的下载量有多少？

根据 npm 官方下载统计，@codaco/app-i18n 在 2026/10/10 – 2026/11/08 这 30 天内被下载 3,553 次，日均约 118 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @codaco/app-i18n 还在维护吗？

最新版本 0\.3\.0 发布于 2026/10/13（27 天前）；至今共发布 3 个版本，其中过去 12 个月发布了 3 个；首次发布于 2026/09/10。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

