ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Gutenberg i18n Filters 详解:用 wp.hooks 过滤器覆写编辑器翻译文本

Gutenberg i18n Filters 详解:用 wp.hooks 过滤器覆写编辑器翻译文本 Gutenberg i18n Filters 详解用 wp.hooks 过滤器覆写编辑器翻译文本【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenbergGutenbergWordPress 块编辑器的前端国际化i18n基于wordpress/i18n包实现其中__()、_x()、_n()、_nx()四个翻译函数在返回结果前会触发一组可编程的过滤器filters允许开发者在运行时覆写任意翻译字符串。本文以官方文档 i18n Filters 为主线结合 wordpress/i18n 包源码讲解这组过滤器的完整签名、参数含义、text domain 专属过滤器用法以及其底层调用链与测试验证帮助你精准定制编辑器界面文案。一、i18n 过滤器是什么wordpress/i18n提供的__()、_x()、_n()、_nx()四个函数负责在前端完成字符串翻译与 PHP 侧的__()、_x()、_n()、_nx()一一对应。它们基于 Tannin即全局wp.hooks做二次加工。也就是说这四个函数的返回值不是一成不变的任何插件或主题都可以通过注册过滤器覆写某条翻译从而在不动源码、不改语言包的前提下定制界面文案。可用的过滤器共四个i18n.gettexti18n.gettext_with_contexti18n.ngettexti18n.ngettext_with_context在 create-i18n.ts 中这些钩子的命名被一段正则约束任何以i18n.(n?gettext|has_translation)开头的钩子都会被视为 i18n 过滤器参与联动const I18N_HOOK_REGEXP /^i18n\.(n?gettext|has_translation)(_|$)/;二、四个过滤器的回调签名过滤器回调接收的参数与其 PHP 侧对应函数一致。注意第一个参数是已经查表得到的翻译结果translation后续参数才是原文与上下文信息回调必须返回一个字符串通常原样返回translation。2.1 i18n.gettext对应__()无上下文、无复数形式function i18nGettextCallback( translation, text, domain ) { return translation; }参数说明translation已查得的译文可能仍是原文text待翻译的原始字符串domain文本域text domain未指定时为undefined2.2 i18n.gettext_with_context对应_x()带 gettext 上下文消歧function i18nGettextWithContextCallback( translation, text, context, domain ) { return translation; }参数说明translation已查得的译文text待翻译的原始字符串context翻译上下文用于区分同一原文在不同场景的不同译法domain文本域2.3 i18n.ngettext对应_n()按数字选择单复数function i18nNgettextCallback( translation, single, plural, number, domain ) { return translation; }参数说明translation已查得的单数或复数译文single单数形式的原文plural复数形式的原文number用于判定单复数的数字domain文本域2.4 i18n.ngettext_with_context对应_nx()同时带上下文与复数function i18nNgettextWithContextCallback( translation, single, plural, number, context, domain ) { return translation; }参数说明translation已查得的译文single单数形式的原文plural复数形式的原文number用于判定单复数的数字context翻译上下文domain文本域三、源码视角过滤器如何接入翻译流程默认的 i18n 单例在 default-i18n.ts 中创建它把全局的defaultHooks注入 i18n 实例const i18n createI18n( undefined, undefined, defaultHooks );因此默认实例的四个翻译函数一定会经过过滤器管线。以__()为例create-i18n.ts 中的实现是这样的const __ ( text, domain ) { let translation dcnpgettext( domain, undefined, text ); if ( ! hooks ) { return translation; } translation hooks.applyFilters( i18n.gettext, translation, text, domain ); return hooks.applyFilters( i18n.gettext_ getFilterDomain( domain ), translation, text, domain ); };从中可以读出三条关键设计先查表、后过滤dcnpgettextTannin 的核心查表函数先返回翻译结果过滤器只在结果之上做覆写或修饰。两级过滤器串联先触发通用过滤器如i18n.gettext再触发 domain 专属过滤器如i18n.gettext_woocommerce后者的translation入参是前者处理后的结果形成管道式串联。domain 缺失时的回退规则getFilterDomain定义为( domain ) domain || default见 create-i18n.ts所以当调用方没有传入 domain例如翻译 WordPress 核心字符串时专属过滤器会退化为i18n.gettext_default等形式。_x()、_n()、_nx()的实现结构与__()完全同构只是参数更多_x()额外透传context_n()透传single、plural、number_nx()则同时透传number与context见 create-i18n.ts。四、基本用法覆写单条翻译在插件或主题的 JS 入口中使用wp.hooks.addFilter注册回调即可。以下示例把块编辑器中Create Reusable block这条字符串替换为组织内部的惯用语// Define our filter callback. function myPluginGettextFilter( translation, text, domain ) { if ( text Create Reusable block ) { return Save to MyOrg block library; } return translation; } // Adding the filter wp.hooks.addFilter( i18n.gettext, my-plugin/override-add-to-reusable-blocks-label, myPluginGettextFilter );addFilter的第二个参数是唯一的命名空间标识namespace用于区分不同的注册者也是后续removeFilter、hasFilter的依据。钩子系统本身由 _Hooks 类 提供applyFilters会按优先级依次调用该过滤器上的所有回调并传递返回值。五、text domain 专属过滤器推荐做法从性能角度出发优先使用带 text domain 的过滤器这样你的回调只会针对该 domain 下的字符串执行而不会在每一次__()调用时都被调用。用法是在标准过滤器名后追加下划线和 domain 名。例如要过滤 domain 为woocommerce的字符串可用的过滤器是i18n.gettext_woocommercei18n.gettext_with_context_woocommercei18n.ngettext_woocommercei18n.ngettext_with_context_woocommerce示例// Define our filter callback. function myPluginGettextFilter( translation, text, domain ) { if ( text You’ve fulfilled all your orders ) { return All packed up and ready to go. Good job!; } return translation; } // Adding the filter wp.hooks.addFilter( i18n.gettext_woocommerce, my-plugin/override-fulfilled-all-orders-text, myPluginGettextFilter );关于defaultdomain 的约定如果要过滤的字符串其 domain 为undefined例如 WordPress 核心字符串则在构造过滤器名时使用defaulti18n.gettext_defaulti18n.gettext_with_context_defaulti18n.ngettext_defaulti18n.ngettext_with_context_default这一点与源码中getFilterDomain的回退逻辑完全吻合undefineddomain 会映射为字符串default从而命中上述过滤器。六、过滤器调用顺序通用优先、domain 其次单元测试 create-i18n.tstest 对这一行为做了精确断言。测试同时注册了通用过滤器与 domain 过滤器并验证了结果拼接顺序test( __() calls filters, () { const hooks createHooksWithI18nFilters(); const i18n createI18n( undefined, undefined, hooks ); expect( i18n.__( hello ) ).toEqual( hello/i18n.gettext/i18n.gettext_default ); expect( i18n.__( hello, domain ) ).toEqual( hello/i18n.gettext/i18n.gettext_domain ); } );可见处理链是查表结果 → 通用过滤器 → domain 专属过滤器。_x()、_n()、_nx()的测试create-i18n.tstest也验证了同样的顺序并覆盖了复数数量1与2两种分支。由此可以推导出两条实用结论若你希望兜底覆写让所有 domain 的同类字符串都受影响注册通用过滤器若你只针对某个 domain或核心default覆写注册 domain 专属过滤器且它能覆盖通用过滤器的结果因为它在链尾。七、进阶主题hasTranslation、isRTL 与订阅机制原文档聚焦于四个gettext过滤器但 i18n 钩子体系还包括一个官方未在本文列出、却被正则明确支持的过滤器i18n.has_translation同样支持i18n.has_translation_default与 domain 专属变体。hasTranslation()用于判断某字符串在当前 locale 数据中是否已有译文create-i18n.ts 中它同样经过通用过滤器 domain 专属过滤器两级管线回调签名为function hasTranslationFilterCallback( hasTranslation, single, context, domain ) { return hasTranslation; }测试中的用法示例当single Always且无 context、domain 为default时强制返回true见 create-i18n.tstest。与之相关的还有两个实用 APIisRTL()通过_x( ltr, text direction )判断当前语言是否为从右到左RTL例如希伯来语he、阿拉伯语ar英语、法语等 LTR 语言返回falsecreate-i18n.ts。subscribe()订阅 locale 数据变化当i18n.*过滤器被添加或移除时实例会通过hookAdded/hookRemoved动作通知订阅者重新渲染create-i18n.ts。八、多实例场景createI18n 与自定义 hooks如果你不想使用全局的wp.hooks可以通过createI18n()创建带独立 locale 数据与 hooks 的 i18n 实例import { createHooks } from wordpress/hooks; import { createI18n } from wordpress/i18n; const hooks createHooks(); const i18n createI18n( localeData, my-domain, hooks ); // 每个实例维护自己的 locale 数据与过滤器管线单元测试 create-i18n.tstest 证明了多个实例互不干扰分别setLocaleData后同一hello在两个实例中返回不同译文。createI18n的完整 APIsetLocaleData、addLocaleData、resetLocaleData、getLocaleData等参见 i18n README 与 types.ts。九、实战建议与注意事项命名空间必须唯一addFilter的第二个参数如my-plugin/override-xxx是移除过滤器时removeFilter的依据务必保持稳定且唯一。尽量用 domain 专属过滤器回调只在目标 domain 下触发避免在每次翻译调用上产生无谓开销。牢记translation可能是原文当语言包缺失时dcnpgettext会回退返回原文你的过滤器仍应正确处理这种情况通常返回translation兜底。上下文与复数参数不可遗漏_x()/_nx()的context、_n()/_nx()的number都是精确匹配的关键覆写逻辑应同时比对它们避免误伤其他场景的同名文案。配合服务端国际化前端过滤器只影响已加载到浏览器的字符串完整的国际化流程含 POT 提取、语言包生成可参考 internationalization 指南。十、延伸阅读i18n Filters 官方文档本文主体来源wordpress/i18n 包文档安装与全部 API__、_x、_n、_nx、sprintf、setLocaleData、isRTL等create-i18n.ts 源码过滤器管线的具体实现default-i18n.ts 源码默认单例与全局wp.hooks的绑定i18n 单元测试过滤器顺序、domain 回退、复数分支的权威行为验证wordpress/hooks 源码addFilter/applyFilters等钩子原语的实现Filters 参考指南目录Gutenberg 其他 JavaScript 过滤器【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表