ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

wp-calypso 的 Babel 插件 babel-plugin-preserve-i18n:在压缩产物中保住 WordPress 翻译调用

wp-calypso 的 Babel 插件 babel-plugin-preserve-i18n:在压缩产物中保住 WordPress 翻译调用 前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载本篇文章围绕 wp-calypso 仓库中的 Babel 插件 automattic/babel-plugin-preserve-i18n 展开介绍它如何在构建与压缩阶段保留__( Hello )这类 WordPress i18n 函数调用语法使 WP i18n 提取工具在产物包括被 Terser 压缩后的 bundle中仍能识别并抽取翻译字符串。读完本文你将掌握该插件的设计动机、AST 变换原理、scope 绑定维护细节以及它在 Calypso 共享 Babel 配置中的真实接入方式。一、插件要解决什么问题Calypso 的代码中大量使用 WordPress 官方的国际化函数例如import { __, _x } from wordpress/i18n; __( Hello ); _x( World );在正常编译流程中import语句会被 Babel 降级为require/ CommonJS 形式进入生产 bundle 后__、_x这类本地变量名往往会被压缩器如 Terser重命名成a、b之类的短名。一旦调用点变成a( Hello )WordPress 的 i18n 提取工具例如 WP-CLI 的i18n make-pot或 Calypso 自己基于 babel-plugin-i18n-calypso 的 POT 生成流程就无法再通过__( 字符串 )的固定模式扫描到待翻译文本导致字符串漏翻。babel-plugin-preserve-i18n的思路与社区中的babel-plugin-optimize-react对 React 导入做类似变换一脉相承通过别名化导入、再用const重新声明原名把翻译函数名钉死在产物中。插件 README 中给出了完整的目标输出import { __ as alias__, _x as alias_x } from wordpress/i18n; const __ alias__; const _x alias_x; __( Hello ); _x( World );变换后调用点的写法__( Hello )与变换前逐字一致依旧可以在输出 bundle 中被 i18n 工具扫描出来而 Terser 压缩时若配合mangle.reserved选项将__、_x等名字加入保留名单则即使经过 minify这个可识别的调用模式依然完整存在见 README.md。二、源码实现AST 变换的完整流程插件的主入口是 src/index.js其 package.json 将main指向该文件。整个实现只有两个核心部分一个负责收集并别名化导入的函数以及一个挂载在ImportDeclaration上的 visitor。1. 翻译函数白名单const i18nImports new Set( [ __, _n, _nx, _x ] );插件只对来自wordpress/i18n的这四个命名导入做处理覆盖了 WordPress i18n 中最常用的四个形态__( text )普通翻译、_x( text, context )带上下文、_n( single, plural, number )复数、_nx( single, plural, number, context )复数 上下文。不在集合内的导入如sprintf、isRTL等原样保留不做任何干预。2. 收集导入并生成别名collectAllImportsAndAliasThem核心函数collectAllImportsAndAliasThem( path )完成三步工作src/index.js#L6-L38第一步校验模块来源。只有t.isStringLiteral( node.source ) node.source.value wordpress/i18n的导入声明才会进入处理逻辑避免误伤其他包的同名函数。第二步遍历 specifiers 并别名化。对每个ImportSpecifier即具名导入要求imported与local都是Identifierimport { __ as foo }这类带本地别名的写法也能正确处理随后命中白名单后记录{ original: localNode.name, aliased: alias localNode.name }即原名__的别名是alias__用t.importSpecifier( t.identifier( alias localNode.name ), t.identifier( importedNode.name ) )替换原 specifier把导入目标改成别名调用path.scope.removeBinding( localNode.name )移除原本地绑定的注册循环结束后path.scope.registerDeclaration( path )把修改后的导入声明重新注册到作用域。第三步返回收集到的别名列表供 visitor 使用。3. 在导入声明后插入 const 重声明visitor 只监听一个节点类型visitor: { ImportDeclaration( path ) { const aliases collectAllImportsAndAliasThem( path ); if ( aliases.length 0 ) { const declarations aliases.map( ( { original, aliased } ) t.variableDeclarator( t.identifier( original ), t.identifier( aliased ) ) ); const aliasDeclarationNode t.variableDeclaration( const, declarations ); path.insertAfter( aliasDeclarationNode ); const aliasDeclarationPath path.getNextSibling(); path.scope.registerDeclaration( aliasDeclarationPath ); } }, },见 src/index.js#L40-L57要点拆解当收集到至少一个别名时把每条记录生成一个variableDeclarator( 原名, 别名 )最终拼成一个const声明节点例如const __ alias__, _x alias_x;通过path.insertAfter把该声明紧跟在 import 语句之后插入使__、_x以const绑定形式继续存在于模块作用域中插入后立刻通过path.getNextSibling()拿到新节点的 Path并registerDeclaration到作用域保证后续对__、_x的引用能被正确解析。这种先removeBinding、再registerDeclaration的作用域管理是插件正确性的关键它让 Babel 在后续遍历中不会因绑定信息过期而报错也确保同一文件内既有的__( Hello )调用语义不发生任何变化。4. 插件元信息返回的对象带有name: babel-plugin-preserve-i18n便于 Babel 在报错和调试信息中标识该插件。包本身以module.exports function ( babel ) { ... }的形式导出标准的 Babel 插件工厂函数依赖 Babel 传入的babel.typest完成全部节点构造。三、包配置与工程形态从 package.json 可以看到该包的完整工程信息字段值说明nameautomattic/babel-plugin-preserve-i18n发布在 npm 上的包名version1.0.0当前版本descriptionA Babel plugin to preserves translation functions even when minified.一句话概括插件目标mainsrc/index.js入口即插件实现licenseGPL-2.0-or-later开源许可证publishConfig.accesspublic允许公开发布devDependenciesautomattic/calypso-eslint-overrides、automattic/calypso-typescript-config均workspace:^仅用于仓库内 lint 与 TS 配置仓库地址指向githttps://github.com/Automattic/wp-calypso.gitdirectory字段精确标注到packages/babel-plugin-preserve-i18n。其 tsconfig.json 仅扩展了 automattic/calypso-typescript-config 的js-package.json预设——注意插件本身是纯 JavaScript 实现TS 配置只服务于仓库统一的工程约束。四、在 Calypso 构建管线中的真实接入babel-plugin-preserve-i18n不是孤立的实验代码而是 Calypso 共享 Babel 配置的一等公民。在 packages/calypso-babel-config/package.json 中它被声明为calypso-babel-config的运行时依赖并在默认 preset 中直接启用plugins: [ require.resolve( babel/plugin-proposal-class-properties ), [ require.resolve( babel/plugin-transform-runtime ), { corejs: false, helpers: true, regenerator: false, useESModules: false, /* ... */ }, ], require.resolve( automattic/babel-plugin-preserve-i18n ), require.resolve( emotion/babel-plugin ), ],见 presets/default.js#L38-L54也就是说任何基于automattic/calypso-babel-config默认预设的 Calypso 模块包括 client 与 packages 下的 React/JS 源码在 Babel 编译阶段都会自动经过本插件的变换。与之配合的还有 config.js 定义的build_pot环境该环境启用automattic/babel-plugin-i18n-calypso并可通过outputPOT参数指定 POT 文件输出目录、注入content-type与x-generator头。整体链路可以概括为源码写入__( Hello )Babel默认 preset含 preserve-i18n把 import 别名化并插入const重声明调用点写法原样保留生产构建经 Terser 压缩时配合mangle.reserved保留翻译函数名构建产物bundle中依然存在可被扫描的__( Hello )调用模式WP i18n 工具或build_pot环境下的 i18n-calypso 插件据此抽取全部待翻译字符串生成 POT。这个顺序保证了翻译字符串提取与代码压缩优化两条需求不互相打架——这正是该插件在大型 JS 应用中的价值所在。五、适用边界与使用注意事项从源码结构与 README 可以梳理出以下几点实践须知只处理命名导入不处理默认导入visitor 中仅匹配t.isImportSpecifierimport i18n from wordpress/i18n这类默认导入不会触发变换模块来源必须精确匹配wordpress/i18n字符串字面量是唯一目标即使其他包也导出了__也不会被误伤别名命名规则别名固定为alias 本地名如alias__、alias_nx如果源码中恰巧存在同名标识符理论上存在冲突风险这也是使用时应留意的边界情况与 Terser 的配合是锦上添花而非必需即使不配置mangle.reserved经插件变换后的 bundle 在未压缩状态下也完全可被 i18n 工具提取配置mangle.reserved才能保证 minify 之后调用名不被改写压缩阶段的保护对象是调用模式而非字符串本身插件只关心函数名与调用形态的保留字符串常量仍由常规的 i18n 工具链负责收集与去重。如果希望在自有项目中复用它最直接的方式是像 Calypso 一样把它加入 Babel 配置的plugins数组本仓库为 workspace 依赖可通过yarn workspace引用automattic/babel-plugin-preserve-i18n随后按上文链路配置构建与提取流程即可。六、小结babel-plugin-preserve-i18n是一个小而精准的 Babel 插件它以一次 AST 变换import 别名化 const原名重声明 scope 绑定维护解决了压缩产物中的翻译调用可被提取这一国际化工程难题。核心证据集中在 src/index.js 的几十行实现以及 presets/default.js 中的真实接入点它服务的目标函数集合__、_n、_nx、_x与 WordPress i18n 工具的扫描模式一一对应。理解这个插件的原理也就理解了大型 JavaScript 应用中编译优化与字符串提取如何通过作用域与 AST 操作达成平衡。赞分享前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载相关推荐wp-calypso 国际化构建基石babel-plugin-i18n-calypso 提取 translate 调用生成 POT 全解析wp calypso 国际化构建基石babel plugin i18n calypso 提取 translate 调用生成 POT 全解析 本文围绕 pack前端CMSWordPress Gutenberg 的 Babel 插件 babel-plugin-makepot从 JS 源码自动生成 gettext POT 翻译模板WordPress Gutenberg 的 Babel 插件 babel plugin makepot从 JS 源码自动生成 gettext POT 翻译模板后端前端探索Babel插件魔法babel-plugin-macros探索Babel插件魔法 babel plugin macros 项目简介 Babel https://babeljs.io/ 是JavaScript的编译器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表