--- createdAt: 2026-05-10 updatedAt: 2026-05-10 title: Sync PO 插件 description: 将 Intlayer 字典与 Gettext PO 文件同步。在使用 Intlayer 管理、翻译和测试消息的同时,保留现有的 i18n。 keywords: - Intlayer - Sync PO - Gettext - i18n - 翻译 slugs: - doc - plugin - sync-po youtubeVideo: https://www.youtube.com/watch?v=MpGMxniDHNg history: - version: 8.9.4 date: 2026-05-10 changes: "初始 Sync PO 插件文档" --- # Sync PO (i18n 桥接) - 支持 ICU / i18next 的 Sync PO 将 Intlayer 作为现有 i18n 栈的补充。此插件使您的 Gettext PO 消息与 Intlayer 字典保持同步,以便您可以: - 保留现有的基于 PO 的翻译工作流。 - 使用 Intlayer (CLI、CI、供应商、CMS) 管理和翻译您的消息,无需重构您的应用。 - 发布针对各生态系统的教程和 SEO 内容,同时建议将 Intlayer 作为 PO 管理层。 注意事项和当前范围: - 外部化到 CMS 适用于翻译和经典文本。 - 尚不支持 PO 条目内部的插值、复数/ICU 或其他库的高级运行时功能。 - 可视化编辑器尚不支持第三方 i18n 输出。 ### 何时使用此插件 - 您已经在使用 Gettext PO 文件进行翻译。 - 您希望在不更改渲染运行时的情况下,获得 AI 辅助填充、CI 测试和内容运营。 ## 安装 ```bash pnpm add -D @intlayer/sync-po-plugin # 或 npm i -D @intlayer/sync-po-plugin ``` ## 插件 此包提供两个插件: - `loadPO`:将 PO 文件加载到 Intlayer 字典中。 - 此插件用于从源加载 PO 文件并将其载入 Intlayer 字典。它可以扫描整个代码库并搜索特定的 PO 文件。 此插件可用于: - 如果您使用的 i18n 库强制要求 PO 文件的加载位置,但您希望将内容声明放在代码库中您喜欢的位置。 - 它也可以用于从远程源(如 CMS、API 等)获取消息并将消息存储在 PO 文件中。 > 在底层,此插件将扫描整个代码库并搜索特定的 PO 文件,并将其加载到 Intlayer 字典中。 > 请注意,此插件不会将输出和翻译写回 PO 文件。 - `syncPO`:将 PO 文件与 Intlayer 字典同步。 - 此插件用于将 PO 文件与 Intlayer 字典同步。它可以扫描给定位置并加载与特定 PO 文件模式匹配的 PO。如果您想在使用另一个 i18n 库的同时获得 Intlayer 的优势,此插件非常有用。 ## 同时使用两个插件 ```ts fileName="intlayer.config.ts" import { Locales, type IntlayerConfig } from "intlayer"; import { loadPO, syncPO } from "@intlayer/sync-po-plugin"; const config: IntlayerConfig = { internationalization: { locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], defaultLocale: Locales.ENGLISH, }, // 使当前的 PO 文件与 Intlayer 字典保持同步 plugins: [ /** * 将加载 src 中匹配 {key}.i18n.po 模式的所有 PO 文件 */ loadPO({ source: ({ key }) => `./src/**/${key}.i18n.po`, locale: Locales.ENGLISH, priority: 1, // 确保这些 PO 文件优先于 `./locales/en/${key}.po` 处的文件 }), /** * 将加载输出和翻译并将其写回 locales 目录中的 PO 文件 */ syncPO({ source: ({ key, locale }) => `./locales/${locale}/${key}.po`, priority: 0, }), ], }; export default config; ``` ## `syncPO` 插件 ### 快速开始 将插件添加到您的 `intlayer.config.ts` 并指向您现有的 PO 结构。 ```ts fileName="intlayer.config.ts" import { Locales, type IntlayerConfig } from "intlayer"; import { syncPO } from "@intlayer/sync-po-plugin"; const config: IntlayerConfig = { internationalization: { locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], defaultLocale: Locales.ENGLISH, }, // 使当前的 PO 文件与 Intlayer 字典保持同步 plugins: [ syncPO({ // 每个语言、每个命名空间的布局 source: ({ key, locale }) => `./locales/${locale}/${key}.po`, }), ], }; export default config; ``` 备选方案:每个语言一个文件: ```ts fileName="intlayer.config.ts" import { Locales, type IntlayerConfig } from "intlayer"; import { syncPO } from "@intlayer/sync-po-plugin"; const config: IntlayerConfig = { internationalization: { locales: [Locales.ENGLISH, Locales.FRENCH], defaultLocale: Locales.ENGLISH, }, plugins: [ syncPO({ source: ({ locale }) => `./locales/${locale}.po`, }), ], }; export default config; ``` #### 工作原理 - 读取:插件从您的 `source` 构建器发现 PO 文件并将其作为 Intlayer 字典加载。 - 写入:构建和填充后,它将本地化的 PO 写回相同的路径(带有正确的 Gettext 头)。 - 自动填充:插件为每个字典声明一个 `autoFill` 路径。默认情况下,运行 `intlayer fill` 仅更新 PO 文件中缺失的翻译。 API: ```ts syncPO({ source: ({ key, locale }) => string, // 必填 location?: string, // 可选标签,默认:"sync-po::path/to/source" priority?: number, // 用于冲突解决的可选优先级,默认:0 format?: 'icu' | 'i18next' | 'vue-i18n', // 可选,仅当您的 msgstr 值使用特定插值语法时才需要 }); ``` #### `format` ('icu' | 'i18next' | 'vue-i18n') PO 文件始终是 Gettext Portable Object 文件 —— 这是固定的。此选项仅描述 `msgstr` 值内部使用的 **插值语法**,以便 Intlayer 可以在解析时(通过 `formatDictionary`)将其转换为自己的格式,并在写入输出时转换回来。 - `undefined` _(默认)_:`msgstr` 值被视为普通字符串 —— 不进行转换。大多数 PO 文件使用此选项。 - `'icu'`:`msgstr` 值使用 ICU 消息语法(例如 `{count, plural, one {# item} other {# items}}`)。 - `'i18next'`:`msgstr` 值使用 i18next 插值语法(例如 `{{variable}}`)。 - `'vue-i18n'`:`msgstr` 值使用 Vue I18n 语法。 > 转换由 `@intlayer/chokidar` 的 `formatDictionary` 在加载时应用,并在写入时通过 `formatDictionaryOutput` 反转。对于像 ICU 复数这样的复杂规则,不保证往返的保真度。 **示例 —— PO 文件包含 i18next 风格的插值:** ```ts syncPO({ source: ({ key, locale }) => `./locales/${locale}/${key}.po`, format: "i18next", }), ``` ### 多个 PO 源和优先级 您可以添加多个 `syncPO` 插件来同步不同的 PO 源。当您的项目中有多个翻译源或不同的 PO 结构时,这很有用。 #### 优先级系统 当多个插件针对同一个字典键时,`priority` 参数决定哪个插件优先: - 高优先级数字胜过低优先级数字 - `.content` 文件的默认优先级为 `0` - 插件的默认优先级为 `0` - 具有相同优先级的插件按照它们在配置中出现的顺序进行处理 ```ts fileName="intlayer.config.ts" import { Locales, type IntlayerConfig } from "intlayer"; import { syncPO } from "@intlayer/sync-po-plugin"; const config: IntlayerConfig = { internationalization: { locales: [Locales.ENGLISH, Locales.FRENCH], defaultLocale: Locales.ENGLISH, }, plugins: [ // 主要 PO 源(最高优先级) syncPO({ source: ({ key, locale }) => `./locales/${locale}/${key}.po`, location: "main-translations", priority: 10, }), // 后备 PO 源(较低优先级) syncPO({ source: ({ locale }) => `./fallback-locales/${locale}.po`, location: "fallback-translations", priority: 5, }), // 遗留 PO 源(最低优先级) syncPO({ source: ({ locale }) => `/my/other/app/legacy/${locale}/messages.po`, location: "legacy-translations", priority: 1, }), ], }; export default config; ``` ## Load PO 插件 ### 快速开始 将插件添加到您的 `intlayer.config.ts` 以将现有的 PO 文件作为 Intlayer 字典摄取。此插件是只读的(不会写入磁盘): ```ts fileName="intlayer.config.ts" import { Locales, type IntlayerConfig } from "intlayer"; import { loadPO } from "@intlayer/sync-po-plugin"; const config: IntlayerConfig = { internationalization: { locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], defaultLocale: Locales.ENGLISH, }, plugins: [ // 摄取位于源树中任何位置的 PO 消息 loadPO({ source: ({ key }) => `./src/**/${key}.i18n.po`, // 每个插件实例加载一个语言(默认为配置的 defaultLocale) locale: Locales.ENGLISH, priority: 0, }), ], }; export default config; ``` 备选方案:按语言布局,仍然是只读的(仅加载选定的语言): ```ts fileName="intlayer.config.ts" import { Locales, type IntlayerConfig } from "intlayer"; import { loadPO } from "@intlayer/sync-po-plugin"; const config: IntlayerConfig = { internationalization: { locales: [Locales.ENGLISH, Locales.FRENCH], defaultLocale: Locales.ENGLISH, }, plugins: [ loadPO({ // 只有 Locales.FRENCH 的文件将从此模式加载 source: ({ key, locale }) => `./locales/${locale}/${key}.po`, locale: Locales.FRENCH, }), ], }; export default config; ``` ### 工作原理 - 发现:从您的 `source` 构建器构建一个 glob 并收集匹配的 PO 文件。 - 摄取:使用提供的 `locale` 将每个 PO 文件加载为 Intlayer 字典。 - 只读:不写入或格式化输出文件;如果您需要双向同步,请使用 `syncPO`。 - 自动填充准备:定义一个 `fill` 路径,以便 `intlayer content fill` 可以填充缺失的键。 ### API ```ts loadPO({ // 构建指向您的 PO 的路径。如果您的结构没有语言段,则 `locale` 是可选的 source: ({ key, locale }) => string, // 由此插件实例加载的字典的目标语言 // 默认为 configuration.internationalization.defaultLocale locale?: Locale, // 用于识别源的可选标签 location?: string, // 默认:"plugin" // 用于与其他源进行冲突解决的优先级 priority?: number, // 默认:0 }); ``` ### 行为和约定 - 如果您的 `source` 掩码包含语言占位符,则仅摄取所选 `locale` 的文件。 - 如果掩码中没有 `{key}` 段,则字典键为 "index"。 - 键通过替换 `source` 构建器中的 `{key}` 占位符从文件路径派生。 - 插件仅使用发现的文件,不会伪造缺失的语言或键。 - `fill` 路径从您的 `source` 推导出来,并在您选择启用时用于通过 CLI 更新缺失的值。 ## 冲突解决 当多个 PO 源中存在相同的翻译键时: 1. 具有最高优先级的插件决定最终值 2. 较低优先级的源用作缺失键的后备 3. 这允许您保留遗留翻译,同时逐步迁移到新结构 ## CLI 同步的 PO 文件将被视为与其他 `.content` 文件相同。这意味着,所有 intlayer 命令都将可用于同步的 PO 文件。包括: - `intlayer content test` 测试是否有缺失的翻译 - `intlayer content list` 列出同步的 PO 文件 - `intlayer content fill` 填充缺失的翻译 - `intlayer content push` 推送同步的 PO 文件 - `intlayer content pull` 拉取同步的 PO 文件 有关更多详细信息,请参阅 [Intlayer CLI](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/cli/index.md)。 ## 局限性(当前) - 针对第三方库时不支持插值或复数/ICU。 - 可视化编辑器尚不适用于非 Intlayer 运行时。 - 仅限 PO 同步;不支持非 PO 目录格式。 ## 为什么这很重要 - 我们可以推荐成熟的 i18n 解决方案,并将 Intlayer 定位为补充。 - 我们通过教程利用他们的 SEO/关键词,教程最后建议使用 Intlayer 来管理 PO。 - 将目标受众从“新项目”扩展到“任何已经在使用 i18n 的团队”。