Skip to content

locale 探测失败会被 initialize_global_language 的一次性初始化钉死到重启 #2525

Description

@wehos

utils/language_utils.pyinitialize_global_language()任何情况下都会置 _global_language_initialized = True,包括系统语言探测没拿到有效信号、只能回落默认值的时候:

# 优先级2:从系统设置获取
system_lang = _get_system_language()
_global_language = normalize_language_code(system_lang, format='short')
_global_language_full = normalize_language_code(system_lang, format='full')
logger.info(f"全局语言已初始化(来自系统设置): {_global_language}")
_global_language_initialized = True
return _global_language

_get_system_language() 自带兜底(最终 return 'en'),所以"探测失败"不表现为异常,而是回落值被当成探测结果存下。此后 get_global_language() / get_global_language_full() 命中 _global_language_initialized 直接返回该值,不会再探测 —— 语言(以及 _is_china_region() 定下的 _global_region)被钉死到进程重启。

触发场景

启动瞬间所有信号都不可用时:Steamworks 尚未就绪、NEKO_LANGUAGE 未设、进程继承中性 C.UTF-8、且平台探测恰好失败(macOS 上 defaults 超时、Windows 上 GetUserDefaultLocaleName 异常)。结果是用户明明把系统设成中文,却拿到英文界面 + non-china 选源,重启才能恢复。

说明

这是既有设计,不是某个 PR 引入的回归 —— 92ed2818b~1#1542 合入前)的 initialize_global_language() 已经是同样的写法。#1542 新增的 macOS defaults 探测只是让"探测可能失败"的路径多了一条。

#2523_get_macos_locale() 改成不缓存失败结果(只缓存确定性结论),消除了该函数自身的永久化;但只要上层已经初始化完成,就不会再调到它 —— 所以那层修复对 initialize_global_language() 这条主链路无效,是 Greptile 在 #2523 上指出的。

可能的方向(需要评估,不建议顺手改)

区分「探测到的值」与「兜底默认值」,只在前者置 _global_language_initialized;兜底时保持未初始化,让下一次 getter 重新探测。风险点:

  • _get_system_language() 目前不区分这两种返回,要先给它一个"没探测到"的表达方式
  • 若某平台永远探测不到,每次 getter 都会重跑整个初始化(含 _is_china_region),需要配一个重试上限或时间窗
  • 改的是所有平台共用的初始化语义,不只 macOS

相关:#2523#1542

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions