## Summary
The apps did not set `<html lang>` to the UI locale. stage-tamagotchi
had no `lang`, and stage-web and stage-pocket kept `lang="en"`. The base
font stack has no CJK font. So Chromium picks the fallback font for CJK
text from the document language, and without a matching `lang`, the OS
language decides.
On a macOS with Japanese first in the language list, Simplified Chinese
settings labels mixed two fonts. Hiragino Kaku Gothic W3 rendered the
characters that it has. Simplified-only characters, such as 设, 备, and 对,
fell back to PingFang SC Medium, so they looked bold.
The document language now follows the UI locale. Chromium then picks one
font for each locale, for example PingFang SC for `zh-Hans` and PingFang
TC for `zh-Hant`.
## Changes
- `modules/i18n.ts` of each app sets `document.documentElement.lang` to
the initial locale.
- The code that applies a language change also sets it. This is
`useLanguage` in stage-tamagotchi, and the `settings.language` watcher
in `App.vue` of stage-web and stage-pocket.
- `use-language.test.ts` moves to browser mode as
`use-language.browser.test.ts`. `useLanguage` now uses `document`, and
the node test project has no DOM. The test now uses the real
`localStorage` instead of a `globalThis` stub.
## Verification
Measured on macOS with the language list `ja-US, en-US, zh-Hans-US`. The
Electron 43 build of this repository rendered one Simplified Chinese
label under each `lang` on a test page. `CSS.getPlatformFontsForNode`
reported these fonts:
| `lang` | Fonts for "向所有设备开放 配对令牌" |
| --- | --- |
| none, `en` | Hiragino Kaku Gothic ProN W3 ×8, PingFang SC Medium ×3 |
| `zh-Hans`, `zh-CN` | PingFang SC Medium ×11 |
| `zh-Hant` | PingFang TC Medium ×11 |
- The commit hook ran `moeru-lint --fix`.
- Typecheck and tests did not run locally. CI runs them, including the
moved browser test.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary
Some Korean strings were wrong or out of date. This PR corrects 14
values in 3 files under `packages/i18n/src/locales/ko/`.
- `tamagotchi.stage.controls-island.login`: the Controls Island sign-in
button said 가입하기, which means "sign up". It now says 로그인, as the other
Korean sign-in strings do.
- `settings.pages.connection.*` and
`settings.websocket-secure-enabled.*`: 2770267dc rewrote 12 English
strings on the connection settings page. The Korean values kept the
older text. Eight of them were still English, for example "Connect from
Stage Pocket" for the current "Pairing". They now follow the current
English text.
- The glossary says the mobile edition reads as "Mobile ver." to end
users. The Korean text now says 모바일 버전 and does not use "Stage Pocket"
or "pocket".
- `stage.chat.sessions.new`: the new-conversation button said "+ New"
next to its own plus icon. It now says 새 대화.
This PR is independent. It changes only the `ko` locale. Other locales
still have the same older English in `pages.connection`, but Crowdin
owns them, so this PR does not touch them.
`tamagotchi.stage.about.links.github` keeps `Github`. `GitHub` equals
the English text, and deleting the key fails the locale check.
## Verification
```text
node .github/scripts/check-locales.ts --root packages/i18n/src/locales --base <upstream/main locales> --source-changes warning # passed
pnpm exec eslint packages/i18n/src/locales/ko/settings.yaml packages/i18n/src/locales/ko/stage.yaml packages/i18n/src/locales/ko/tamagotchi/stage.yaml # passed
```
- The pre-commit hook (`moeru-lint --fix`) passed.
- No ko value in the 3 files is equal to its English value.
## Visual changes
| Before | After |
| --- | --- |
|

|

|
| Main window / Controls Island menu, signed out, `ko` | Main window /
Controls Island menu, signed out, `ko` |
|

|

|
| Settings / Connection, `ko` | Settings / Connection, `ko` |
|

|

|
| Floating chat / Conversations drawer, `ko` | Floating chat /
Conversations drawer, `ko` |
How I took the captures:
- I built stage-tamagotchi with `pnpm -F @proj-airi/stage-tamagotchi
build` on Windows 11 and captured it with `vishot capture --target
electron`.
- Each run used a new empty profile (`APP_USER_DATA_PATH`) with
`settings/language` set to `ko` and onboarding marked as done.
- The "Before" build used the same commit with the 3 `ko` files restored
from the merge base (`71b3c178e`). The merge base and this branch differ
only in these files.
- The `qr.token-hint` and `qr.image-alt` values are not in the captures.
They show only when the Pairing panel is open, and that panel shows a
live pairing QR code.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Auto-generated by CI to keep Nix pnpmDeps hash up-to-date.
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Neko <neko@ayaka.moe>