Royal MCP 插件汉化去广告:把 WordPress 插件改成自己的,官方更新再也覆盖不掉

Zou, Ning 发布于 21 小时前 技术实践 3232 字 28 次阅读


WP Mail SMTP 是 WordPress 上装机量最大的发信插件之一,配置 QQ 邮箱、Gmail、各家 API 服务商都靠它。功能没问题,问题有两个:后台越做越像个货架,界面还基本是英文——官方中文包只覆盖 17%。

装好之后打开设置页,顶部 Tab 一共 9 个:一般、邮件日志、告警、附加连接、智能路由、邮件控制、其他、授权,还有一个「获取 Pro」。点开邮件日志会看到一张 Pro 功能的示意图,点开告警是一段「升级后可以收 Slack 通知」的文案,附加连接、智能路由、邮件控制三页的正文加起来不够一屏,共同点只有一个——都要你买 Pro。

真正能用的只有「一般」和「其他」两页。

这篇记录的是把这个插件拆一遍的过程:删掉多少行推广代码、汉化怎么做到不动插件源码、以及打包成能装到别人站点上的形式时踩到的坑。

一、先看数字

改造前后的对比,口径统一按整个插件目录的 PHP 文件统计:

原版 4.10.3改造后 4.10.3.1
PHP 文件733697
PHP 代码行144,245133,791
目录体积9.9 MB8.4 MB
设置页 Tab92(一般、其他)
后台菜单项63
简体中文覆盖17%(358/2109)100%(1669/1669)

删掉的一万行里,纯推广代码占 8,124 行——按 src/ 目录 76,259 行算,是 10.7%;推广图片另占 2.3 MB。剩下的差额是随推广模块一起废弃的死代码。

体积只降了 1.5 MB,因为汉化语言包又补回了 0.78 MB。把语言包摘掉单看代码,是 9.9 MB → 7.6 MB。多出来的那个 PHP 文件就是编译后的语言包(.l10n.php)。

需要说明一点:这些改动对访客端零影响。插件的前端资源加载全部包在 Core.php 的 is_admin() 分支里,前台一个字节都不会少。所以「精简能提速」这个理由在这里不成立,删它纯粹是因为后台看着烦。

二、广告不只在页面上

翻源码之前我以为只是几个页面,实际有七条通道。

设置页 Tab。Area.php 里注册了 AlertsTab、AdditionalConnectionsTab、SmartRoutingTab、ControlTab、GetProTab 等文件,每个文件几十行,主体是一个 product-education 的推广块。

远程运营位。Admin/Notifications.php 里写死了 wpmailsmtpapi.com 的地址,插件会定期拉取一份 JSON 塞进后台通知,内容由厂商运营随时改。这类设计的关键在于:你删不掉它,因为它不在你的服务器上。

周报邮件。Reports/Emails/Summary.php 在 Lite 版的周报正文里嵌了一段「Want More Stats?」加升级按钮。本站 summary_report_email_disabled 是 false,也就是说每周都在收这封带广告的邮件。

测试邮件模板。TestEmail/TestEmail.php 里,用来验证发信是否正常的测试邮件,HTML 版带一个右侧推广栏(列 6 项 Pro 功能 + $50 折扣),纯文本版结尾直接跟一段功能清单和一个 wpmailsmtp.com/lite-upgrade/ 链接。你发一封测试邮件给自己,收到的是一张广告单页。

后台首页 widget。DashboardWidget.php 在图表上盖了一层半透明遮罩,中间弹一个「查看详细邮件统计」的框,按钮是升级。

虚构数据的统计卡。仪表盘的 StatCards.php 里有四个统计卡,其中「Sent 1190」和「Opened 486」是锁定状态,数字打了码。源码注释写得很坦白:teaser 值是设计稿里固定的,跟站点真实数据无关,所以永远不能替换成实际值。换句话说,这两个数字是编的,唯一作用是让你觉得「买了 Pro 就能看到这些」。

匿名安装通道。Connect.php 提供一条 AJAX 接口,可以从远程把你站的插件安装并激活成 Pro 版。这条通道在 Lite 版里就存在。

三、网上那个「过滤 is_pro」的偏方会白屏

搜「WP Mail SMTP 去广告」,最常见的答案是加一段代码把 is_pro() 过滤成 true。在这个插件上照做,后台会 500。

Area.php 里有一行是这么写的:

$is_archive = is_pro() && wp_mail_smtp()->pro->get_logs()->is_archive();

pro 属性只有在真正装了 Pro 版、pro 类被实例化之后才存在。把 is_pro() 伪造成 true,pro 依然是 null,于是访问 null->get_logs() 直接致命错误。

全插件 29 个文件、55 处 is_pro() 分支都是同一个模式:判定为真之后就去找 Pro 的类。伪装授权状态不会解锁功能,只会让代码走进一条原本不存在的路。

正确的做法是反过来——把这些分支连同它们指向的 UI 一起卸载,让 is_pro() 保持 false,插件自然走 Lite 路径。

四、汉化:一行插件代码都没改

汉化部分反而最简单,前提是别把语言包塞进插件目录。

原版自带一个 assets/languages/wp-mail-smtp.pot,共 2109 条待译字符串。官方 zh_CN 语言包覆盖 358 条,17%,剩下 83% 全是空白——尤其是 4.9 之后新增的仪表盘、设置清单、Pro 页面,一个中文字都没有。所以这次基本等于重做。

第一步是把它放在 wp-content/languages/plugins/wp-mail-smtp-zh_CN.{po,mo,l10n.php},不碰插件文件。WordPress 的文本域加载顺序是先查这个全局目录,所以插件升级覆盖插件目录时,语言包依然在。(后来为了打包分发,又迁进了插件内部,见第六节。)

裁掉推广模块后,POT 里还剩 1669 条在用,全部译完,然后做了一轮术语归一:官方译文里 Mailer 译成「邮件程序」,我原来译的是「发信方式」,混在一起同一个界面会出现两种叫法;Email Log 官方是「电子邮件日志」,统一成「邮件日志」;From Email 和 From Name 必须区分开,不然两个字段在中文里都叫「发件人」。最后跑脚本逐条比对占位符(%s / %1$s / %%)和 HTML 标签,0 处不一致。

有个地方汉化不了:Vue 写的设置向导(assets/vue/js/wizard.min.js)是编译产物,插件没有调用 wp_set_script_translations(),标准语言包够不到它。要汉化得改前端源码重新打包,这次没做。

五、两次白屏换来的教训

删代码最怕的不是删错文件,是删完之后 PHP 语法检查全过,一访问就 500。

第一次:Core.php 里有一句 new Connect(),我把 Connect.php 整个删了,用脚本扫了一遍所有 use WPMailSMTP\Connect 确认没有引用,然后部署。结果每个请求都 fatal,整站 500。

原因很简单——Core.php 和 Connect.php 都在 WPMailSMTP 命名空间下,new Connect() 根本不需要 use 语句。按 use 列表做检查的工具,对这种同命名空间的裸类名完全看不见。

第二次:Reports/Reports.php 第 352 行还在调 Area::get_logs_access_capability(),这个方法我随日志页一起删了。这次影响面小,只有设置页 500。

这两次之后补了两道闸。

一是静态链接检查脚本,解析每个文件的 namespace、use 别名,再找 new X(、X::、extends、instanceof 里的类名,逐个查文件是否存在。关键是要做对照:拿同一份脚本对原始 4.10.3 跑一遍,两边都是 23 条误报(PHPMailer 这类动态加载的类),才能证明改造版没有新增悬空引用。只跑改造版看到 23 条,你不知道那是历史遗留还是自己造的。

二是部署后的验证顺序:wp eval 确认插件能加载 → 带登录 Cookie 真实抓一遍后台每个页面 → grep 'PHP Fatal' /www/wwwlogs/wordpress.local.error.log。第三条最有用,nginx 的错误日志里有完整堆栈和行号,而 wp-content/debug.log 是空的。

php -l 通过只说明语法没错,不说明类还在。

六、打包给别人用,卡在语言包上

改完之后想把插件打包成能装到其他站点的 zip,遇到了一个具体问题:语言包在 wp-content/languages/plugins/ 里,不在插件目录里。别人装了这个 zip,界面还是英文。

第一反应是改插件主文件,加一行 load_plugin_textdomain() 指向插件内的 languages/ 目录。翻插件头的时候发现不用改——原版头部已经声明了:

 * Text Domain: wp-mail-smtp
 * Domain Path: /assets/languages

Domain Path 是给 WordPress 找语言包用的。只要把 wp-mail-smtp-zh_CN.mo 放进 assets/languages/,WP 的文本域注册表自己会去那里找,不需要任何代码改动。

验证方法是把全局那份语言包移走,看后台是不是还中文。结果是:

Settings           => 设置
Email Log          => 邮件日志
From Email         => 发件邮箱
Send Test Email    => 发送测试邮件

插件内置的语言包接管了。于是把全局那份一并迁进插件目录,删掉 wp-content/languages/plugins/ 下的旧文件,避免两处不一致——否则哪天只更新了一份,界面会出现一半新一半旧的术语。

最终包 2.68 MB,976 个条目,顶层目录 wp-mail-smtp,用 get_plugin_data() 解析确认 Name、Version、TextDomain、DomainPath、Update URI 都能正确读出,可以后台上传直接安装。

七、必须锁住更新

插件头加了一行 Update URI: false,WordPress 从此不会提示这个插件有新版。

这不是洁癖。官方在 9 月 30 日到 10 月 20 日这 20 天里发了 4 个版本,其中 4.10.0 带权限校验的加固。按这个节奏,任何一次自动更新都会把插件目录整体覆盖,去广告和汉化全部归零。

代价是安全补丁也不会自动来。所以这一行必须和台账一起交付——包里附了一份 XZ-PATCHES.md,记录每个文件的改动点和升级新版时的重做顺序。要跟进官方更新,路径是「下载新版 → 按台账重新裁剪 → 重新生成语言包 → 部署」,而不是点一下「更新」。

八、留下了什么

删掉的都是货架,不是功能。现在这个版本里:

  • 发信方式配置完整保留,SMTP、Gmail、Outlook、SendLayer、Brevo、SMTP.com、Mailgun、SendGrid、Postmark、SparkPost、Zoho、Amazon SES 这些 Lite 版能配的都在
  • 测试邮件、调试事件、代码片段、导入导出、工具页、关于页都还在
  • 后台首页 widget 保留了发信统计,只是去掉了图表遮罩和升级页脚

还有 5 处 get_upgrade_link() 没删,分布在 Pro 选项的点击提示、安装向导的 JSON 配置和 Outlook 发信方式的说明里。它们的共同点是:只有你主动去点一个 Pro 功能时才会弹出来,属「这个功能你的版本用不了」的提示,不是常驻广告位。留着比删掉更合理。

九、结论

这个插件值得留,但值得改。

去广告的收益不在性能——前台一个字节都不受影响——而在于后台终于只剩两个能用的页面,不用每次进去先拨开六层推销。汉化的收益是实的,官方 17% 的覆盖率意味着大部分界面原本是英文,中文用户配一个 SMTP 得半猜半试。

至于 Pro,这次连看都没看它的功能清单。一周发 1 到 6 封通知邮件、单渠道 QQ SMTP 的站点,13 项 Pro 功能里唯一有点用的是「发信失败告警」,而这个用 wp_mail_failed 钩子二十行就能自己写。

改造后的包和台账都放在工作目录,装的站点自己用,也顺手给了两个同样在折腾 WordPress 的朋友。

分享内容:WP Mail SMTP 汉化去广告精简实录:9 个 Tab 里 6 个是广告 分享链接:https://ug.link/xiaozou/filemgr/share-download/?id=855729c3677a488dbc49a6c2cab3ec99 访问密码:2MVE

如果你觉得这篇文章不错,有用的话可以点击下面的“赞赏”支持作者,你的支持是我更新的动力(饿饿吃饭)。

  • reward_image1
  • reward_image2
欢迎来到XiaoZou123,这里是一个电脑极客、数码爱好者网站。我平时喜欢关注数码新闻,研究计算机技术。如果你看我头像觉得我是二次元,那我其实还算不上!
最后更新于 2026-10-29