feat(lang): 构建时可把整个部署固定为一门语言 - #302
Open
wenjianzhang wants to merge 4 commits into
Open
Conversation
An intranet that runs in one language had no way to say so. Since i18n landed every visitor's browser decides, so a deployment that upgrades finds its English-reading staff looking at an English interface, and the only way back was to edit the source. The pinned language outranks both the stored choice and the browser. Over the stored choice on purpose: the deployments that need this have been running long enough that some of their users already went through the switcher, and leaving those visitors where they were would make "this deployment is Chinese" true of everyone except the people who found the switcher first. A value that is not a language we ship fails the build rather than falling back. A typo -- zh_CN, zh, cn -- is otherwise a deployment that quietly keeps following the browser: nothing is missing from the interface, no request fails, and the one person who would ever notice is the operator who thought they had pinned it. vite.config.mjs decides by looking for a pack directory under src/lang, because a config file cannot import the module that holds LOCALES; a unit test holds the two to each other, so a directory that exists is also a language the app will accept. setLocale stops recording the language when the build is pinned. Storage is where a visitor's own choice lives, and writing a build flag into it would outlive the flag: unset VUE_APP_LOCALE later and everyone who ever loaded the site stays in a language they never picked, with the switcher back on screen but already answered.
A dropdown whose entries the deployment will not honour offers a choice and then ignores it: the click loads a language pack and repaints, and the next reload puts everything back, because initialLocale answers to the pinned value rather than to what was stored. The whole component drops out rather than the menu inside it. Both hosts pass a class and an id in, so an element still carrying right-menu-item would keep its share of the navbar's flex row.
Pinned to one language the switcher is gone, and two dozen tests in i18n.spec.ts wait out their timeouts against an interface the suite is not describing: 12 minutes to fail, with nothing on screen to say why. A shell that still has the variable exported from a build is enough to do it. Cleared rather than inherited, for the same reason `locale` is pinned to zh-CN a few lines above.
What the variable does, that a misspelling fails the build rather than being ignored, that adding a language means both a directory and a LOCALES line now, and not to export it while running e2e.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
i18n 上线后留下的缺口:没有任何办法把一套部署固定成一门语言。
src/lang/locales.ts的优先级只有「访客选过的 → 浏览器语言 → zh-CN」,一个纯中文的内网升级上来,英文浏览器的同事就落在英文界面,运维想让所有人继续看中文只能改代码。用法
VUE_APP_LOCALE=zh-CN pnpm build:prod # 或者在 .env.production 里写.env都是空的)—— 现在的行为,访客自己决定zh-CN/en-US—— 全站固定成这门语言,导航栏和登录页的切换器整个不渲染,访客存过的选择也不再生效三个取舍
固定,不是「改默认」。 它压过 localStorage 里的旧选择。需要这个功能的部署通常已经跑了一阵,有人中途用过切换器——把那批人留在原地,「这套部署是中文的」就对所有人成立,除了最先发现切换器的那几位。代价是「保留切换器、只改默认」这个诉求不支持,真有人提再加第二个变量。
拼错让构建失败,不是静默回退。
否则界面看起来一切正常、只是仍跟着浏览器走,而唯一会发现的人是以为自己已经锁上的运维。判据是
src/lang/下有没有对应目录——配置文件 import 不了持有LOCALES的模块,所以另配一条单测把目录清单和LOCALES绑在一起:以后加语言,两边必须同时改。切换器整个不渲染,而不是只藏菜单。 两个宿主都往它身上传了 class 和 id,留一个还挂着
right-menu-item的元素,导航栏那一格就还占着位。一处我自己引入的缺陷
setLocale原本无条件rememberLocale(locale)。固定模式下它会把部署配置写进每个访客的 localStorage——哪天去掉变量重新构建,所有人被钉在从没选过的语言上,切换器回来了但已经替他们答过了。改成固定时不写,访客原本存的值也原样留着。验证
七条反证,全部真红(每条都先确认退化补丁确实落地):
initialLocale不先看固定值fixedLocale不过isLocaleLOCALES加一门没有目录的语言setLocale无条件写 storageVUE_APP_LOCALE真实构建:
VUE_APP_LOCALE=zh_CN pnpm build:prod中止并列出可用语言;en-US构建后 preview 打开——界面英文、#lang-select数量 0、localStorage 里访客存的zh-CN没被覆写;去掉变量重新构建,切换器回来、界面按存的选择变回中文。单测 350 全绿(新增 18 条),e2e 255 全绿,lint 0 error,首屏 486.65 kB 未超预算。
playwright.config.ts顺手把这个变量清空——不清的话,shell 里残留一个就够让 i18n 那套跑 12 分钟然后红一片,而屏幕上没有任何线索。