前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载本篇技术文章以client/lib/translator-jumpstart/模块及其 README 为核心讲解 wp-calypsoWordPress.com 的纯 JS REST API 管理前端如何把外部 Community Translator 服务接入页面从字符串采集、翻译器启动器的显示条件到脚本注入、Jed 翻译表的热更新与调试手段。读完本文你将能够完整理解该模块的调用链与关键状态机并在仓库中定位每一处实现依据。模块定位它负责什么client/lib/translator-jumpstart/是一个极小的模块目录内只有两个文件说明文档 README.md 和全部实现 index.jsx。README 明确了它的职责采集字符串收集经 i18n mixini18n.translate()处理的字符串并把数据挂到全局对象window.translatorJumpstart上供外部 Community Translator 读取按需显示启动器launcher需同时满足以下条件——community-translator在 config 中启用用户在自己的设置中勾选了Enable on page translation选项用户 UI 语言不是英语通过特性检查较大的屏幕且以“无触摸输入”近似判断“有鼠标右键”点击启动器后加载脚本Community Translator 脚本通过loadScript按需注入而非首屏加载。从源码结构看README 中描述的“采集”机制在现行实现中具体落地为 index.jsx 末尾注册的翻译钩子// wrap translations from i18n i18n.registerTranslateHook( ( translation, options ) { return communityTranslatorJumpstart.wrapTranslation( options.original, translation, options ); } );即每次i18n.translate()产出译文时都会经过wrapTranslation统一处理这正是“把页面字符串喂给外部翻译器”的入口。字符串采集wrapTranslation 如何给译文打上“可翻译标记”wrapTranslation( originalFromPage, displayedTranslationFromPage, optionsFromPage )的实现位于 index.jsx#L83-L130。其逻辑与边界条件值得逐条拆解前置短路若isEnabled()或isActivated()为假或调用方传入了textOnly选项表示该字符串不应参与页内编辑翻译直接返回原译文类型防御非字符串的 original、非对象的 options 均被安全归一化options 回退为{}打标记构造一个dataReact 元素携带如下属性——className: translatableCommunity Translator 在 DOM 中识别可翻译节点的依据data-singular英文原文singular 形式data-context当options.context为字符串时写入对应 gettext 的 context/* translators: */data-plural当options.plural为字符串时写入供复数翻译使用。一个容易踩坑的细节data元素是 React 返回的冻结对象源码先Object.assign复制一份再覆写toString使其返回译文否则字符串拼接时会得到[object Object]最后再次Object.freeze以模拟原始 ReactElement 的行为见 index.jsx#L117-L129。激活状态下_shouldWrapTranslations true页面上所有带data-singular等属性的节点即构成 Community Translator 的操作目标集这也解释了为什么“启用/停用”需要重渲染后文toggle()中的i18n.reRenderTranslations()。启动器显示条件isEnabled 与 isValidBrowser 的逐层判断README 列出的四个显示条件在 isEnabled() 中按顺序实现为五个短路检查README 条件源码实现说明UI 语言不是英语canBeTranslated( currentUser.localeSlug )若 locale 为空或不可翻译则禁用canBeTranslated来自automattic/i18n-utilsutils.ts#L67隐含区域变体可用canBeTranslated( currentUser.localeVariant )对“没有官方 GP 翻译集”的 locale 变体如某些地区变体禁用用户设置已加载_isUserSettingsReady在 userSettings 就绪前一律返回 false避免误判用户开启了Enable on page translation_isTranslatorEnabled由trackTranslatorStatus()写入见“埋点与状态”一节大屏幕 非触摸设备isValidBrowser()见下文isValidBrowser()index.jsx#L292-L298当前实现非常直接isValidBrowser() { if ( isMobile() ) { return false; } return true; },其中isMobile来自automattic/viewport对应 packages/viewport。源码注释index.jsx#L71解释了动机“在 touch 交互方案完善之前暂时对移动设备禁用翻译器”这与 README 中“大屏幕上、无触摸 ≈ 有右键”的特性检查描述是一致的——Community Translator 的交互右键菜单/悬浮编辑依赖鼠标能力。页面翻译数据window.translatorJumpstart 的结构外部 Community Translator 脚本运行前会把自身需要的“页面翻译上下文”读取自window.translatorJumpstart。这个对象由模块内的translationDataFromPage常量初始化index.jsx#L17-L27并在toggle()中一次性赋给 windowindex.jsx#L237const translationDataFromPage { localeCode: en, languageName: English, pluralForms: nplurals2; plural(n ! 1), contentChangedCallback() {}, glotPress: { url: https://translate.wordpress.com, project: wpcom, translation_set_slug: default, }, };各字段的含义与更新时机localeCode/languageName/pluralForms当前 UI 语言信息由updateTranslationData()在 locale 文件加载后更新contentChangedCallback组件内容变化时的回调初始为空函数翻译器加载后会被替换见“脚本加载与激活”glotPress告知 Community Translator 与哪个 GlotPress 实例和项目通信——这正是 README “Environment specific functionality”一节的核心。updateTranslationData()index.jsx#L174-L202的更新规则若localeCode未变化则直接跳过避免重复处理pluralForms依次尝试plural_forms、Plural-Forms、plural-forms三种键名兜底沿用默认值languageName从automattic/languagespackages/languages中按langSlug查找并用正则/^(?:[a-z]{2,3}|[a-z]{2}-[a-z]{2})\s-\s/去掉语言条目名里的语言代码前缀glotPress.translation_set_slug根据 locale 变体查translateSetSlugs映射表缺省为default。环境相关行为GlotPress 实例、项目与翻译集README 指出启动器决定了 Community Translator 与哪个 GlotPress 实例、哪个项目通信默认是 WordPress.com 的翻译项目projects/wpcom在非生产环境中使用的项目为test而非wpcom。结合源码可以看到translationDataFromPage.glotPress的静态默认值即为该实例与wpcom项目index.jsx#L22-L26而翻译集 slug 通过translateSetSlugsindex.jsx#L14-L16做了一层“locale 变体 → GP 翻译集”的映射// lookup for the translation set slug on GP const translateSetSlugs { de_formal: formal, };也就是说德语正式变体de_formal会被路由到 GP 上的formal翻译集其余语言走default。非生产环境的test项目选择从源码结构看属于部署环境注入/配置的范畴当前仓库中该对象以wpcom为代码内默认值实际以运行环境的注入结果为准。脚本注入与激活流程toggle() 的状态机toggle()index.jsx#L209-L269是启动器点击后的核心入口可分为三条路径路径一脚本尚未加载。先把translationDataFromPage赋给window.translatorJumpstart再用loadjQueryDependentScript( injectUrl, callback )注入外部脚本该函数来自automattic/load-script对应 packages/load-script。注入 URL 由setInjectionURL()拼成const communityTranslatorBaseUrl https://widgets.wp.com/community-translator/; const communityTranslatorVersion 1.160729; // ... injectUrl communityTranslatorBaseUrl jsFile ?v communityTranslatorVersion;即从 widgets 域拉取community-translator.min.js并附带版本参数index.jsx#L204-L207。加载成功后执行window.communityTranslator.registerTranslatedCallback( communityTranslatorJumpstart.updateTranslation ); activate();路径二激活activate。function activate() { _shouldWrapTranslations true; i18n.reRenderTranslations(); window.communityTranslator.load(); debug( Translator activated ); return true; }先置位_shouldWrapTranslationsisActivated()返回它再重渲染所有译文——这一步让全页节点都带上data-singular等标记最后调用翻译器load()。路径三停用deactivate。对称地调用window.communityTranslator.unload()、清掉_shouldWrapTranslations并reRenderTranslations()把数据标记从 DOM 中全部移除。另有一个防御分支若在init之前就触发了 toggleinjectUrl尚未生成只记录 debug 日志并返回 false。翻译结果回写updateTranslation 与 Jed 格式用户在 Community Translator 中提交翻译后翻译器会回调updateTranslation( newTranslation )index.jsx#L272-L290updateTranslation( newTranslation ) { const locale i18n.getLocale(); const key newTranslation.key; const plural newTranslation.plural; const translations newTranslation.translations; // jed expects: // context\004singular: [plural, translatedSingular, translatedPlural...] locale[ key ] [ plural ].concat( translations ); i18n.setLocale( locale ); },关键点在于它直接改写 i18n 底层 locale 对象并调i18n.setLocale()key 采用 Jed 约定的context\004singular形式数组首元素是 plural 规则其后是单数/复数译文。也就是说页内翻译不是 DOM 文本替换而是把用户译文合并进 Jed 语言表后续所有渲染都自然使用新译文。与之配合的还有一个组件更新钩子index.jsx#L306-L312// callback when translated component changes. // the callback is overwritten by the translator on load/unload, so were returning it within an anonymous function. i18n.registerComponentUpdateHook( () { if ( typeof translationDataFromPage.contentChangedCallback function ) { return translationDataFromPage.contentChangedCallback(); } } );translationDataFromPage.contentChangedCallback就是translationDataFromPage里的空函数槽Community Translator 在 load/unload 时覆写它用于在页面内容变化时通知翻译器重新扫描。注意toggle()开头还会重新安装一个“未注册时告警”版本index.jsx#L210-L217若翻译器已激活但回调未被注册会输出一条一次性 debug 警告。初始化时机与语言切换的重新初始化init( user, isUserSettingsReady )index.jsx#L132-L172负责建立用户数据并串联整个启动过程顺序为从i18n.getLocale()取当前语言 JSON解析出localeSlug即 localeCode与localeVariant保存_user无用户数据则 debug 记录“initialization failed because user data is not ready”并返回有语言数据时调用updateTranslationData()否则记录“trying to initialize translator without loaded language”幂等保护initialized已为 true 时直接返回更新_isUserSettingsReady未就绪则中止isEnabled()为假时记录“not initializing, not enabled”并返回全部通过后才置initialized true。模块最后还有一行订阅index.jsx#L329-L330// re-initialize when new locale data is loaded i18n.subscribe( communityTranslatorJumpstart.init.bind( communityTranslatorJumpstart ) );这保证了用户切换 UI 语言后locale 数据重新加载整个模块会自动重新走一遍初始化——语言名、复数规则、翻译集 slug 全部随新 locale 刷新。埋点与状态trackTranslatorStatustrackTranslatorStatus( isTranslatorEnabled )index.jsx#L314-L327是 README 中“用户在自己的设置里开启Enable on page translation”这一条件的写入方export function trackTranslatorStatus( isTranslatorEnabled ) { const newSetting isTranslatorEnabled; const changed _isTranslatorEnabled ! newSetting; const tracksEvent newSetting ? calypso_community_translator_enabled : calypso_community_translator_disabled; if ( changed _isTranslatorEnabled ! undefined ) { debug( tracksEvent ); recordTracksEvent( tracksEvent, { locale: i18n.getLocaleSlug() } ); } _isTranslatorEnabled newSetting; }它做两件事更新模块内部_isTranslatorEnabled状态isEnabled()依赖它并在状态发生变化时通过recordTracksEvent来自calypso/lib/analytics/tracks上报calypso_community_translator_enabled/calypso_community_translator_disabled事件事件属性携带当前 locale slug。首次调用_isTranslatorEnabled undefined只记录状态不上报避免初始化噪声。调试指南用 debug 库验证整条链路README 给出的调试方法可直接在浏览器控制台使用该模块使用debug库命名空间为calypso:community-translator见 index.jsx#L9只看翻译器本身localStorage.setItem( debug, calypso:community-translator )同时包含 i18n 显示译文的信息localStorage.setItem( debug, calypso:i18n,calypso:community-translator )结合源码中的 debug 日志点可以精确验证每个阶段Successfully initializedinit 通过、loading community translator/Script loaded!脚本注入、Translator activated/Translator deactivatedtoggle、skipping updating translation data with same localeCode语言未变化时的短路等。小结一次“开启页内翻译”的完整链路把上述各部分串起来用户在 wp.com 客户端开启页内翻译后的完整链路是用户在设置页切换开关 →trackTranslatorStatus(true)置位_isTranslatorEnabled并上报埋点i18n.subscribe触发init()→updateTranslationData()写入 locale、复数规则、window.translatorJumpstart所需的 GlotPress 配置启动器出现的前提语言可翻译、设置就绪、非移动端由isEnabled()/isValidBrowser()把关点击启动器 →toggle()注入community-translator.min.jswidgets 域、版本参数固定为1.160729脚本就绪后registerTranslatedCallback(updateTranslation)activate()_shouldWrapTranslations true→reRenderTranslations()让全页译文节点带上data-singular/data-context/data-plural标记用户提交翻译 →updateTranslation()把译文按 Jed 格式合并进 locale →i18n.setLocale()生效无需刷新页面。如需继续深入可依次查看 translator-jumpstart 模块说明、模块实现、canBeTranslated 语言判定 以及 load-script 脚本加载包。需要留意的前提限制该功能默认仅面向桌面端移动端被isValidBrowser()排除、仅在语言可翻译且用户显式开启时激活且外部脚本来自 widgets 域属于 wp.com 线上环境的服务。赞分享前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载相关推荐如何用kiss-translator轻松实现网页双语翻译新手完整指南如何用kiss translator轻松实现网页双语翻译新手完整指南 还在为看不懂外文网页而烦恼吗kiss translator这款开源双语翻译插件能让你前端如何快速实现屏幕翻译Screen Translator 完整使用指南如何快速实现屏幕翻译Screen Translator 完整使用指南 Screen Translator 是一款强大的开源屏幕翻译工具集成了屏幕捕捉、OCR桌面应用OCRScreen Translator完整教程三步实现屏幕文字智能翻译还在为阅读外文内容而烦恼吗Screen Translator作为一款强大的屏幕捕获、OCR识别和智能翻译工具能够将屏幕上的任何文字即时翻译成你需要的语言彻桌面应用OCR上一篇3分钟彻底搞懂SMAPI星露谷物语模组加载神器下一篇OfficeCLI终极指南无需安装Office的免费自动化办公神器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
ESP32 -O2 优化崩溃排查:volatile、内存屏障与防御性编码 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 3:56:01
AI辅助实战:Web与Android离线地图方案从瓦片下载到加载 做项目最怕遇到什么场景?辛辛苦苦把方案做完了,结果客户现场没有外网,或者说内网环境根本拉不到地图数据。之前我接手一个野外巡检类的项目,一开始用的在线地图,跑到山区里信号一弱,整个界面直接白屏&#… · 2026/9/25 3:56:01
PMOS缓启动电路设计:米勒平台效应分析与RC参数计算实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 3:55:49
Inoproshop指令库与库文件详解:从安装调用到封装避坑 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:25:25
SpringBoot学生考勤管理系统源码实战:环境搭建、数据库导入与二次开发 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:25:25
higgsfield项目深度解析:从强化学习原理到PyTorch实战 很多人第一眼看到“higgsfield”这个词,脑子里蹦出来的可能是物理课上那个给粒子赋予质量的希格斯场。我第一次在开源社区刷到这个项目名,也愣了一下,以为是某个理论物理方向的代码库。点进去才发现,这其实是一个聚焦强化学习和自… · 2026/9/25 4:25:19
汽车IMU原理与实战:从六轴感知到智能驾驶定位基石 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:25:13
ISO/SAE 21434网络安全合规落地:从风险评估到供应链治理 简介:本资源为ISO/SAE DIS 21434:2020(E)《道路车辆—网络安全工程》国际标准草案官方英文原版PDF文档,面向汽车电子工程师、信息安全研究人员、整车及零部件企业合规与功能安全团队,以及参与智能网联汽车认证与开发的技术人员。该草案构建了… · 2026/9/25 4:25:13
Elsevier期刊排版全指南:Neurocomputing投稿格式与LaTeX模板实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:25:07
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37