前不久遇到一个坑:多语言商城环境下,用户在繁体中文页点击购买跳转登录页后,语言突然变成英文。查了半天,发现是 URL 参数和 LocalStorage 在竞态条件下的优先级没理清。把过程记下来,顺便总结一套靠谱的状态同步方案。
一、Bug 场景
用户点击"立即购买"→ 跳转登录页 → 登录页重定向 → 返回后语言状态丢失,页面变为英文。
用户在商城的中文商品页(繁体中文 zh_HK)浏览,点击购买跳转到登录页。登录页加载后,语言变为英文,用户体验断裂。
二、排查过程
最开始怀疑传参丢了。检查 login() 函数:
const lang = window.store?.app?.lang || "en_US";
const loginUrl = `https://.../login?lang=${lang}`;
window.location.href = loginUrl;复现后发现 loginUrl 里明明白白写着 ?lang=zh_HK,参数没丢。
真正的问题在登录页:初始化时没有优先读 URL 里的 ?lang=zh_HK,而是直接读了 Local Storage 的 language。这个字段可能是用户上次访问时留下的 en_US。
商城和登录页同域部署,Local Storage 按域名共享。登录页的逻辑是:先读 LS 的 language,URL 参数被忽略了。另外,登录页的 i18n 可能不支持 zh_HK,只支持 zh_CN,即使传对了也会 fallback 成英文。解决办法是在 i18n 里加 zh_HK → zh_CN 映射。
三、修复方案
1. 双重保险模式:跳转前主动同步状态至 LocalStorage
既然登录页只认 Local Storage,那就在跳转前,强行把正确的语言写入 Local Storage:
// 1. 获取最准确的语言参数(优先 URL,其次 Store,兜底英文)
const lang = getUrlValue("lang") || window.store?.app?.lang || "en_US";
// 2. 【关键】跳转前主动同步 Local Storage
try {
localStorage.setItem("language", encodeURIComponent(lang));
} catch (e) {
console.warn("Local Storage access denied", e);
}
// 3. 带着参数跳转(双重保险)
window.location.href = `${loginUrl}?lang=${encodeURIComponent(lang)}`;2. 优先级策略:LocalStorage(用户选择)> URL 参数 > Fallback
页面刚加载时,别盲目信任 store 或 window 里的状态。URL 参数往往是跨页无状态场景下最可信的数据源。localStorage 操作记得包 try-catch,兼容隐私模式。
四、总结
几条经验:数据信任链建议 URL > Store > Fallback;同域 Local Storage 方便但要注意优先级和污染;localStorage 要 try-catch,否则隐身模式可能白屏。