记一次 Halo 后台界面突然变成英文:一场浏览器缓存引发的假故障

分类记录
标签Halo博客AI生成
记一次 Halo 后台界面突然变成英文:一场浏览器缓存引发的假故障
本文使用 MCP 工具自动创建,内容根据作者真实经历由 AI 整理生成。

前言:后台突然「说英文」了

2026-10-16 凌晨,我照常打开 Halo 后台准备做点日常维护,在转换插件联系表单中的旧模板后愣住了:左侧菜单、按钮、各种提示文案全都变成了英文。我靠,前一秒还是好好的,这时我突然想起来 Halo 社区 中的一篇帖子:安装插件朋友圈之后 全部变成英文 。

当时的第一反应是语言设置被改掉了,于是进设置里把语言从简体中文切到英文,再切回简体中文。结果发现一个很有意思的现象:其他语言都显示正常,唯独简体中文这一份是英文——也就是说简体中文的语言包没有生效,界面回退到了默认语言。

既然只有某一份语言资源异常,那问题就不在「整个后台崩了」,而是某个资源文件加载失败。顺着这个方向查下去,很快就在日志里找到了答案。

排查过程:五步定位到浏览器缓存

整个过程我按顺序记录了下来,前面四步都在做「排除」,最后一步才真正解决问题:

切换后台语言,发现只有「简体中文」异常,其他语言正常显示。查看后台日志,发现请求 i18n 资源时返回 500,并伴随 ZipException。切换用户、清除 Cookie,界面依然是英文,说明与账号和会话无关。换一个浏览器打开后台,正常;再用隐私模式打开,同样正常。在当前浏览器按下 Ctrl + Shift + R 强制刷新,界面恢复中文,问题解决。

服务端日志:一份 i18n 资源返回了 500

第二步提到的报错,是这次排查最关键的一条线索。在后台日志里找到了这样一条记录(时间戳刚好和我发现问题的时间对得上):

2026-10-16T02:04:09.148+08:00 ERROR 1 --- [loomBoundedElastic-87912] b.w.a.e.AbstractErrorWebExceptionHandler : [c14bcc85-12902]  500 Server Error for HTTP GET "/ui-assets/virtual_intlify-i18n-2-PT1tSPn9.js"

java.util.zip.ZipException: invalid stored block lengths
	at java.base/java.util.zip.InflaterInputStream.read(Unknown Source) ~[na:na]
	Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below: 
Error has been observed at the following site(s):
	*__checkpoint ⇢ run.halo.app.security.InitializeRedirectionWebFilter@2b058bfd
	*__checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy@1d1fd2aa
	*__checkpoint ⇢ run.halo.seo.tools.redirect.AdvancedRedirectWebFilter@66c3825
	*__checkpoint ⇢ run.halo.moments.rss.OldRssRouteRedirectionFilter@4c644176
	*__checkpoint ⇢ com.timxs.bbs.comment.BbsLockedCommentFilter@51017b62
	*__checkpoint ⇢ com.xhhao.insight.metrics.RequestObservationFilter@71f090c
	*__checkpoint ⇢ top.ilay.authpasskey.PasskeyLoginContextWebFilter@46e76e1d
	*__checkpoint ⇢ run.halo.seo.tools.traffic.SearchTrafficFilter@2f76bdc1
	*__checkpoint ⇢ run.halo.seo.tools.crawl.CrawlRecordFilter@2166fda3
	*__checkpoint ⇢ cc.ryanc.staticpages.endpoint.RewriteOnNotFoundFilter@57062700
	*__checkpoint ⇢ run.halo.router.TrailingSlashRedirectFilter@112cbca7
	*__checkpoint ⇢ run.halo.app.infra.webfilter.AdditionalWebFilterChainProxy@178c6261
	*__checkpoint ⇢ org.springframework.web.filter.reactive.ServerWebExchangeContextFilter@78e50fca
	*__checkpoint ⇢ run.halo.app.infra.webfilter.LocaleChangeWebFilter@128a188a
	*__checkpoint ⇢ org.springframework.web.filter.reactive.UrlHandlerFilter@5cfe28e1
	*__checkpoint ⇢ run.halo.app.theme.UserLocaleRequestAttributeWriteFilter@2bf4fa1
	*__checkpoint ⇢ HTTP GET "/ui-assets/virtual_intlify-i18n-2-PT1tSPn9.js" [ExceptionHandlingWebHandler]
Original Stack Trace:
		at java.base/java.util.zip.InflaterInputStream.read(Unknown Source) ~[na:na]
		at java.base/java.io.FilterInputStream.read(Unknown Source) ~[na:na]
		at java.base/java.nio.channels.Channels$ReadableByteChannelImpl.read(Unknown Source) ~[na:na]
		at org.springframework.core.io.buffer.DataBufferUtils$ReadableByteChannelGenerator.accept(DataBufferUtils.java:994) ~[spring-core-7.0.9.jar:7.0.9]
		at org.springframework.core.io.buffer.DataBufferUtils$ReadableByteChannelGenerator.accept(DataBufferUtils.java:970) ~[spring-core-7.0.9.jar:7.0.9]
		at reactor.core.publisher.FluxGenerate.lambda$new$0(FluxGenerate.java:58) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.FluxGenerate$GenerateSubscription.slowPath(FluxGenerate.java:270) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.FluxGenerate$GenerateSubscription.request(FluxGenerate.java:212) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.FluxUsing$UsingFuseableSubscriber.request(FluxUsing.java:319) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.request(Operators.java:2325) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.request(FluxConcatMapNoPrefetch.java:338) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.request(FluxContextWrite.java:138) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.requestUpstream(FluxSubscribeOn.java:134) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.onSubscribe(FluxSubscribeOn.java:127) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onSubscribe(FluxContextWrite.java:103) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.onSubscribe(FluxConcatMapNoPrefetch.java:163) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.FluxLimitRequest$FluxLimitRequestSubscriber.onSubscribe(FluxLimitRequest.java:132) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.FluxJust.subscribe(FluxJust.java:69) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.InternalFluxOperator.subscribe(InternalFluxOperator.java:67) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.run(FluxSubscribeOn.java:197) ~[reactor-core-3.8.7.jar:3.8.7]
		at reactor.core.scheduler.BoundedElasticThreadPerTaskScheduler$SchedulerTask.run(BoundedElasticThreadPerTaskScheduler.java:1016) ~[reactor-core-3.8.7.jar:3.8.7]
		at java.base/java.lang.VirtualThread.run(Unknown Source) ~[na:na]

这条日志的信息量其实很明确:浏览器在请求 /ui-assets/ 下那份名为 virtual_intlify-i18n-2-PT1tSPn9.js 的界面资源时,服务端返回了 500;而异常发生在解压读取(Inflate)的环节,说明服务端拿到的这份资源的压缩数据是损坏或不完整的,解压直接失败。

为什么界面会「退回英文」

Halo 后台的界面文案是由一份 i18n 资源包提供的,文件名里的 virtual_intlify-i18n-2-*.js 就是它的构建产物。这份 JS 加载失败时,前端并不会白屏或弹报错窗口,而是回退到默认语言(英文),于是看上去就像「语言设置丢了」——这也是我一开始走弯路、跑去反复切换语言的原因。

结合上面的排查过程,整件事基本可以还原成这样:某次请求中,这份资源被写入了一份损坏的内容,浏览器把这坏掉的一份存进了本地缓存;之后每次打开后台都直接复用这份缓存,简体中文就一直「变成英文」。换浏览器和隐私模式命中不到这份缓存,所以一切正常;而 强制刷新会绕过缓存重新拉取,拿到完整文件后界面立刻恢复。

在出问题的浏览器中按下 强制刷新后,后台界面立刻恢复为简体中文,之后也再没有复发。整个过程没有改动任何服务端配置,根源只是浏览器里的一份损坏缓存。

几条顺手记下的经验

1. 先分清是「服务端坏了」还是「本地缓存坏了」:换浏览器或隐私模式正常,基本可以判定是本地缓存问题,而不是 Halo 本身出故障。
2. 不要急着清空全部网站数据:先试一次强制刷新,避免把登录态、主题偏好等一起清掉。
3. 顺手看一眼日志:像这次的 ZipException: invalid stored block lengths,能直接告诉你坏掉的是哪个静态资源。
4. 如果强制刷新也无效:那就要怀疑服务端那份资源真的损坏了,可以尝试重启 Halo、重新部署 Halo,再不行就到社区反馈。

这次故障本身并不严重,但排查路径挺典型:先用「切换语言」缩小范围,再用「换浏览器 / 隐私模式」区分服务端与本地,最后一步强刷收尾。下次遇到「某个界面元素突然不对,但换台设备就好了」的情况,不妨先想想是不是又被缓存摆了一道。