diff --git a/README.md b/README.md index 421ffc2..d26081d 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Despite the local folder name, the first argument is the Omarchy source checkout A local-source install pins `omarchy-dev` and `omarchy-settings-dev`, since the published builds share their version number but lack the local changes. `IgnorePkg` in `/etc/pacman.conf` makes updates skip them, and a `pre-refresh-pacman` hook (in the user's `~/.config/omarchy/hooks` and in `/etc/skel`) puts that line back after `omarchy refresh pacman`. `/etc/pacman.d/hooks/00-omarchy-pin-local-builds.hook` aborts any transaction that would still replace them. Remove all three to take the published packages. -The configurator asks for the region on its first screen. China reruns the installer in cage + foot, a console that draws Chinese: it opens on a bilingual region screen, keeps a US keyboard, and every later screen and the install progress read in Chinese. Choosing Global there returns to the VT, which applies the chosen keymap; without a working display China continues in English on the VT. The Chinese text lives in `OMARCHY_ZH` tables beside the English it replaces. +The configurator asks for the language on its first screen: English or Simplified Chinese. Chinese reruns the installer in cage + foot, a console that draws Chinese, with Noto Sans Mono CJK unpacked from the offline mirror's `noto-fonts-cjk`. It opens on a bilingual language screen, offers only keyboards with a US keymap (cage keeps a US layout) and preselects Chinese (Simplified, Pinyin); every later screen and the install progress read in Chinese. Choosing English there returns to the VT, which applies the chosen keymap. Without a working display or the font, Chinese continues in English on the VT. Either way a Chinese install sets the target's `LANG` to `zh_CN.UTF-8` through archinstall's `locale_config`. The language never decides the region: that follows the timezone. The Chinese text lives in `OMARCHY_ZH` tables beside the English it replaces. Use `--dev` or `--rc` to build against those package channels. Both `--dev` and `--edge` select the dev packages from the edge mirror. diff --git a/bin/omarchy-iso-test b/bin/omarchy-iso-test index 5e2e1b3..414d415 100755 --- a/bin/omarchy-iso-test +++ b/bin/omarchy-iso-test @@ -17,7 +17,8 @@ # or Chinese (Simplified, Pinyin)/(Traditional, Zhuyin). # OMARCHY_PATH must be the source tree used to build the ISO. # --encrypt Drive the encrypted install flow (default: unencrypted) -# --region REGION Pick global (default) or cn on the first screen +# --language LANG Pick en (default) or zh on the first screen; zh keeps the +# preselected Chinese (Simplified, Pinyin) keyboard # --provision Drive the deferred-provisioning install flow: no user during install, the # first boot runs omarchy-provision-owner and creates it there # --reuse-base Skip the install phase if a base image already exists @@ -43,7 +44,7 @@ MEMORY=8192 INSTALL_TIMEOUT=2400 BOOT_TIMEOUT=600 ENCRYPT=false -REGION=global +INSTALL_LANGUAGE=en PROVISION=false REUSE_BASE=false INSTALL_ONLY=false @@ -61,7 +62,7 @@ while (($#)); do case "$1" in --keyboard) KEYBOARD_LABEL="$2"; shift ;; --encrypt) ENCRYPT=true ;; - --region) REGION="$2"; shift ;; + --language) INSTALL_LANGUAGE="$2"; shift ;; --provision) PROVISION=true ;; --reuse-base) REUSE_BASE=true ;; --install-only) INSTALL_ONLY=true ;; @@ -92,8 +93,12 @@ if [[ ! -f ${ISO:-} ]]; then exit 1 fi -if [[ $REGION != "global" && $REGION != "cn" ]]; then - echo "--region must be global or cn, not $REGION" >&2 +if [[ $INSTALL_LANGUAGE != "en" && $INSTALL_LANGUAGE != "zh" ]]; then + echo "--language must be en or zh, not $INSTALL_LANGUAGE" >&2 + exit 1 +fi +if [[ $INSTALL_LANGUAGE == "zh" && $KEYBOARD_LABEL != "English (US)" ]]; then + echo "--language zh takes the preselected Pinyin keyboard; drop --keyboard" >&2 exit 1 fi case "$KEYBOARD_LABEL" in @@ -103,12 +108,12 @@ esac omarchy-pkg-add qemu-full edk2-ovmf socat imagemagick tesseract tesseract-data-eng tesseract-data-chi_sim -# After the region screen a China install reads in Chinese. +# After the language screen a Chinese install reads in Chinese. OCR_LANGS=eng -[[ $REGION == "cn" ]] && OCR_LANGS=eng+chi_sim -# region_text picks the text a screen shows in this run. -region_text() { - if [[ $REGION == "cn" ]]; then +[[ $INSTALL_LANGUAGE == "zh" ]] && OCR_LANGS=eng+chi_sim +# lang_text picks the text a screen shows in this run. +lang_text() { + if [[ $INSTALL_LANGUAGE == "zh" ]]; then printf '%s' "$2" else printf '%s' "$1" @@ -123,7 +128,7 @@ if [[ $KEYBOARD_LABEL != "English (US)" ]]; then BASE_NAME+="-$(printf '%s' "$KEYBOARD_LABEL" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g')" fi $ENCRYPT && BASE_NAME+="-encrypted" -[[ $REGION == "cn" ]] && BASE_NAME+="-cn" +[[ $INSTALL_LANGUAGE == "zh" ]] && BASE_NAME+="-zh" $PROVISION && BASE_NAME+="-provision" BASE_DIR="$REPO_DIR/test-runs/$BASE_NAME" RUN_DIR="$BASE_DIR/runs/$(date +%Y%m%d-%H%M%S)" @@ -273,8 +278,8 @@ ocr_screen() { screendump "$shot" [[ -s $shot ]] || return 0 magick "$shot" -colorspace gray -negate -resize 150% "$prepped" 2>/dev/null || return 0 - # The logo and the black strip under foot throw tesseract off CJK, so China runs also read between them, without spaces. - if [[ $REGION == "cn" ]]; then + # The logo and the black strip under foot throw tesseract off CJK, so Chinese runs also read between them, without spaces. + if [[ $INSTALL_LANGUAGE == "zh" ]]; then magick "$shot" -gravity north -chop 0x35% -gravity south -chop 0x4% -colorspace gray -negate -resize 150% "$prepped.text.png" 2>/dev/null || return 0 { tesseract "$prepped" - --psm 6 -l "$OCR_LANGS"; tesseract "$prepped.text.png" - --psm 6 -l "$OCR_LANGS"; } 2>/dev/null | sed 'p; s/ //g' || true else @@ -686,28 +691,35 @@ drive_configurator() { capture_console "success-installer-00-greeter" press ret - # Region comes first: Global on top, China below, either one preselected. - wait_for_screen "Select region" 300 - capture_console "success-installer-01-region" - if [[ $REGION == "cn" ]]; then press end; else press home; fi + # Language comes first: English on top, Chinese below. + wait_for_screen "Select language" 300 + capture_console "success-installer-01-language" + if [[ $INSTALL_LANGUAGE == "zh" ]]; then press end; else press home; fi press ret - # Global asks for the keyboard; China reruns in cage + foot on a bilingual region screen with a US keyboard. Ctrl+C on either defers provisioning. - wait_for_screen "$(region_text "keyboard layout" "选择区域")" 300 + # Chinese reruns in cage + foot on a bilingual language screen, Chinese preselected. + if [[ $INSTALL_LANGUAGE == "zh" ]]; then + wait_for_screen "选择语言" 300 + capture_console "success-installer-01-language-cjk" + press ret + fi + + # The keyboard follows; Ctrl+C there defers provisioning. + wait_for_screen "$(lang_text "keyboard layout" "键盘布局")" 300 capture_console "success-installer-01-keyboard-layout" if $PROVISION; then press ctrl-c # arm "prepare for another owner" - wait_for_screen "$(region_text "another owner" "另一位")" 30 + wait_for_screen "$(lang_text "another owner" "另一位")" 30 capture_console "success-installer-02-prepare-confirm" press ret # "Yes, prepare for another owner" is the affirmative default # Jumps straight to disk selection, then the overwrite confirm. - wait_for_screen "$(region_text "install disk" "安装磁盘")" 60 + wait_for_screen "$(lang_text "install disk" "安装磁盘")" 60 capture_console "success-installer-03-prepare-install-disk" press ret - wait_for_screen "$(region_text "recovery possible" "无法恢复")" 60 + wait_for_screen "$(lang_text "recovery possible" "无法恢复")" 60 capture_console "success-installer-04-prepare-disk-warning-encrypted" if ! $ENCRYPT; then press ctrl-c @@ -731,27 +743,27 @@ drive_configurator() { press ret # Normal flow: user step comes before disk selection. - wait_for_screen "$(region_text "Username" "用户名")" 120 + wait_for_screen "$(lang_text "Username" "用户名")" 120 type_text "$GUEST_USER" capture_console "success-installer-02-username" press ret - wait_for_screen "$(region_text "Password" "密码")" 60 + wait_for_screen "$(lang_text "Password" "密码")" 60 type_text "$GUEST_PASSWORD" capture_console "success-installer-03-password" press ret - wait_for_screen "$(region_text "Must match" "确认")" 60 + wait_for_screen "$(lang_text "Must match" "确认")" 60 type_text "$GUEST_PASSWORD" capture_console "success-installer-04-password-confirmation" press ret - wait_for_screen "$(region_text "Full name" "姓名")" 60 + wait_for_screen "$(lang_text "Full name" "姓名")" 60 type_text "Omarchy Test" capture_console "success-installer-05-full-name" press ret - wait_for_screen "$(region_text "Email address" "邮箱")" 60 + wait_for_screen "$(lang_text "Email address" "邮箱")" 60 type_text "test" if [[ $KEYBOARD_LABEL == "Japanese" ]]; then press bracket_left @@ -764,30 +776,30 @@ drive_configurator() { capture_console "success-installer-06-email" press ret - wait_for_screen "$(region_text "Hostname" "主机名")" 60 + wait_for_screen "$(lang_text "Hostname" "主机名")" 60 type_text "$GUEST_HOSTNAME" capture_console "success-installer-07-hostname" press ret - wait_for_screen "$(region_text "Timezone" "时区")" 180 # tzupdate geo-guess can take a moment + wait_for_screen "$(lang_text "Timezone" "时区")" 180 # tzupdate geo-guess can take a moment capture_console "success-installer-08-timezone" press ret - wait_for_screen "$(region_text "look right" "正确")" 60 + wait_for_screen "$(lang_text "look right" "正确")" 60 capture_console "success-installer-09-review" press ret - wait_for_screen "$(region_text "install disk" "安装磁盘")" 60 + wait_for_screen "$(lang_text "install disk" "安装磁盘")" 60 capture_console "success-installer-10-install-disk" press ret # the single virtio disk - wait_for_screen "$(region_text "installation mode\|recovery possible" "安装方式\|无法恢复")" 60 - if ocr_screen | grep -qi "$(region_text "installation mode" "安装方式")"; then + wait_for_screen "$(lang_text "installation mode\|recovery possible" "安装方式\|无法恢复")" 60 + if ocr_screen | grep -qi "$(lang_text "installation mode" "安装方式")"; then capture_console "success-installer-11-install-mode" press ret # "Full disk install" is preselected fi - wait_for_screen "$(region_text "recovery possible" "无法恢复")" 60 + wait_for_screen "$(lang_text "recovery possible" "无法恢复")" 60 capture_console "success-installer-12-disk-warning-encrypted" if ! $ENCRYPT; then press ctrl-c # toggles the confirm to the unencrypted flow @@ -891,8 +903,8 @@ wait_for_install() { while true; do text=$(ocr_screen) - # OCR cannot read the Chinese reboot button, so China matches the title above it. - if grep -qi "$(region_text "Reboot Now" "安装完成")" <<<"$text"; then + # OCR cannot read the Chinese reboot button, so Chinese runs match the title above it. + if grep -qi "$(lang_text "Reboot Now" "安装完成")" <<<"$text"; then log "Install finished. Confirming the reboot prompt." capture_console "success-installer-15-reboot" press ret @@ -908,7 +920,7 @@ wait_for_install() { return 0 fi - if grep -qi "$(region_text "installation stopped" "安装已停止")" <<<"$text"; then + if grep -qi "$(lang_text "installation stopped" "安装已停止")" <<<"$text"; then capture_console "failure-installer-installation-stopped" echo "Install failed — screenshot saved to $RUN_DIR" >&2 return 1 diff --git a/builder/build-iso.sh b/builder/build-iso.sh index d25b745..471762f 100755 --- a/builder/build-iso.sh +++ b/builder/build-iso.sh @@ -124,8 +124,8 @@ cp "/tmp/$NODE_FILENAME" "$build_cache_dir/airootfs/opt/packages/" # The selected omarchy-settings package is needed here so its post_install hook # drops Omarchy's plymouthd.conf into /etc/plymouth before mkarchiso builds the # live initramfs. -# cage, foot and the two fonts give China installs a console that draws Chinese. -arch_packages=(linux-t2 git gum jq openssl plymouth ttfx tzupdate omarchy-keyring "$OMARCHY_SETTINGS_PACKAGE" lvm2 cryptsetup parted cage foot ttf-jetbrains-mono wqy-microhei) +# cage and foot give Chinese installs a console that draws Chinese. +arch_packages=(linux-t2 git gum jq openssl plymouth ttfx tzupdate omarchy-keyring "$OMARCHY_SETTINGS_PACKAGE" lvm2 cryptsetup parted cage foot) printf '%s\n' "${arch_packages[@]}" >> "$build_cache_dir/packages.x86_64" # The live ISO boots linux-t2 (see airootfs/etc/mkinitcpio.d/linux-t2.preset), so diff --git a/configs/airootfs/root/.automated_script.sh b/configs/airootfs/root/.automated_script.sh index ef44b26..90d1ad3 100644 --- a/configs/airootfs/root/.automated_script.sh +++ b/configs/airootfs/root/.automated_script.sh @@ -94,6 +94,16 @@ warm_offline_mirror & warm_pid=$! trap 'kill "$warm_pid" 2>/dev/null' EXIT +# The CJK console's font comes from the offline mirror's noto-fonts-cjk, not the live image. +unpack_cjk_font() { + local packages=(/var/cache/omarchy/mirror/offline/noto-fonts-cjk-*.pkg.tar.zst) + if ((${#packages[@]} != 1)) || [[ ! -f ${packages[0]} ]]; then + echo "Expected one noto-fonts-cjk package in the offline mirror, found: ${packages[*]}" >&2 + return 1 + fi + bsdtar -xf "${packages[0]}" -C / usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc +} + cd /root # Autoinstall: a cidata drive carrying the configurator's own output files # stands in for the wizard. omarchy-cidata-load copies them into /root and @@ -102,7 +112,7 @@ if /usr/local/bin/omarchy-cidata-load; then echo "Autoinstall configuration found on cidata drive; skipping the configurator." export OMARCHY_UI_INTERACTIVE=no else - # China moves to cage + foot, which draw Chinese; Global moves back to the VT, which applies keymaps. + # Chinese moves to cage + foot, which draw Chinese; English moves back to the VT, which applies keymaps. cjk_relaunch=10 vt_return=11 if [[ -n ${OMARCHY_CJK_CONSOLE:-} ]]; then @@ -115,17 +125,23 @@ else cjk_runtime=/run/omarchy-cjk-console mkdir -p -m 700 "$cjk_runtime" rm -f "$cjk_runtime/cjk-console-started" "$cjk_runtime/return-to-vt" + if ! unpack_cjk_font; then + echo "The Chinese font could not be unpacked from the offline mirror; continuing in English." + unset OMARCHY_CJK_RELAUNCH + OMARCHY_INSTALL_LANGUAGE=zh ./configurator && status=0 || status=$? + continue + fi cage_status=0 - env -u OMARCHY_CJK_RELAUNCH XDG_RUNTIME_DIR=$cjk_runtime OMARCHY_CJK_CONSOLE=1 OMARCHY_INSTALL_REGION=cn \ + env -u OMARCHY_CJK_RELAUNCH XDG_RUNTIME_DIR=$cjk_runtime OMARCHY_CJK_CONSOLE=1 OMARCHY_INSTALL_LANGUAGE=zh \ LANG=C.UTF-8 WLR_RENDERER=pixman cage -- foot -c /usr/share/omarchy-iso/foot.ini "$0" || cage_status=$? if [[ -f $cjk_runtime/return-to-vt ]]; then - OMARCHY_INSTALL_REGION=global ./configurator && status=0 || status=$? + OMARCHY_INSTALL_LANGUAGE=en ./configurator && status=0 || status=$? elif [[ -f $cjk_runtime/cjk-console-started ]]; then exit "$cage_status" else echo "The Chinese console could not start (cage exit $cage_status); continuing in English." unset OMARCHY_CJK_RELAUNCH - OMARCHY_INSTALL_REGION=cn ./configurator && status=0 || status=$? + OMARCHY_INSTALL_LANGUAGE=zh ./configurator && status=0 || status=$? fi done if [[ -n ${OMARCHY_CJK_CONSOLE:-} ]] && ((status == vt_return)); then diff --git a/configs/airootfs/root/configurator b/configs/airootfs/root/configurator index c65ceb3..c4ed7ec 100644 --- a/configs/airootfs/root/configurator +++ b/configs/airootfs/root/configurator @@ -45,8 +45,6 @@ OMARCHY_ZH+=( ["Hostname"]="主机名" ["Keyboard"]="键盘" ["Region"]="区域" - ["Global"]="全球" - ["China"]="中国" ["[Skipped]"]="[已跳过]" ["Yes"]="是" ["No, change it"]="否,去修改" @@ -271,15 +269,24 @@ notice() { # STEP 1: KEYBOARD LAYOUT -# .automated_script.sh moves China into the CJK console and Global back to the VT, which applies keymaps. -apply_region_language() { - if [[ $region == "cn" && -n ${OMARCHY_CJK_RELAUNCH:-} ]]; then +# The target's LANG follows the language picked on the first screen. +target_lang() { + if [[ $language == "zh" ]]; then + echo zh_CN.UTF-8 + else + echo en_US.UTF-8 + fi +} + +# .automated_script.sh moves Chinese into the CJK console and English back to the VT, which applies keymaps. +apply_language() { + if [[ $language == "zh" && -n ${OMARCHY_CJK_RELAUNCH:-} ]]; then exit "$OMARCHY_CJK_RELAUNCH" fi - if [[ $region == "global" && -n ${OMARCHY_VT_RETURN:-} ]]; then + if [[ $language == "en" && -n ${OMARCHY_VT_RETURN:-} ]]; then exit "$OMARCHY_VT_RETURN" fi - if [[ $region == "cn" && -n ${OMARCHY_CJK_CONSOLE:-} ]]; then + if [[ $language == "zh" && -n ${OMARCHY_CJK_CONSOLE:-} ]]; then export OMARCHY_INSTALL_LANG=zh else unset OMARCHY_INSTALL_LANG @@ -299,16 +306,14 @@ keyboard_form() { say --foreground 8 "$(omarchy_text "Press Ctrl+C to prepare this machine for another owner.")" echo - omarchy_prompt_region && status=0 || status=$? + omarchy_prompt_language && status=0 || status=$? if ((status == 0)); then - apply_region_language - # cage keeps its US layout, so the CJK console offers no other. - if [[ -n ${OMARCHY_CJK_CONSOLE:-} ]]; then - keyboard="us" - keyboard_label="English (US)" - else - omarchy_prompt_keyboard && status=0 || status=$? - fi + apply_language + local layouts=$OMARCHY_KEYBOARD_LAYOUTS selected="English (US)" + [[ $language == "zh" ]] && selected="Chinese (Simplified, Pinyin)" + # cage keeps its US layout, so the CJK console offers only US-keymap keyboards. + [[ -n ${OMARCHY_CJK_CONSOLE:-} ]] && layouts=$(awk -F'|' '$2 == "us"' <<<"$layouts") + OMARCHY_KEYBOARD_LAYOUTS=$layouts omarchy_prompt_keyboard "$selected" && status=0 || status=$? fi ((status == 0)) && break @@ -385,10 +390,10 @@ user_step() { # The timezone selects the region (mirrors and repositories), using the # same lookup as the orchestrator. Global installs get no extra row. - local summary_region region_row="" - summary_region=$(cd /usr/share/omarchy-iso 2>/dev/null && python -m orchestrator.region "$timezone") || summary_region="global" - if [[ $summary_region != "global" ]]; then - region_row="\n$(omarchy_text Region),$summary_region" + region=$(cd /usr/share/omarchy-iso 2>/dev/null && python -m orchestrator.region "$timezone") || region="global" + region_row="" + if [[ $region != "global" ]]; then + region_row="\n$(omarchy_text Region),$region" fi # Add manual padding since gum table -p doesn't respect padding @@ -937,7 +942,7 @@ run_partition_execute() { "locale_config": { "kb_layout": "$keyboard", "sys_enc": "UTF-8", - "sys_lang": "en_US.UTF-8" + "sys_lang": "$(target_lang)" }, "mirror_config": { "custom_repositories": [], @@ -1139,15 +1144,15 @@ select_installation() { defer_provisioning=false install_target="full_disk" -# A rerun arrives with the console language chosen; otherwise Global. -region="${OMARCHY_INSTALL_REGION:-global}" +# A rerun arrives with the language chosen; otherwise English. +language="${OMARCHY_INSTALL_LANGUAGE:-en}" # Let the live VT reach its settled width before the first screen so the logo # isn't measured against the transient 80-column boot console. wait_for_stable_terminal -if [[ -n ${OMARCHY_INSTALL_REGION:-} ]]; then - apply_region_language +if [[ -n ${OMARCHY_INSTALL_LANGUAGE:-} ]]; then + apply_language else greeter fi @@ -1336,7 +1341,7 @@ cat <<-_EOF_ >user_configuration.json "locale_config": { "kb_layout": "$keyboard", "sys_enc": "UTF-8", - "sys_lang": "en_US.UTF-8" + "sys_lang": "$(target_lang)" }, "mirror_config": { "custom_repositories": [], diff --git a/configs/airootfs/usr/share/omarchy-iso/foot.ini b/configs/airootfs/usr/share/omarchy-iso/foot.ini index 7660000..1397fbc 100644 --- a/configs/airootfs/usr/share/omarchy-iso/foot.ini +++ b/configs/airootfs/usr/share/omarchy-iso/foot.ini @@ -1,6 +1,6 @@ -# The China installer's console: the VT's Tokyo Night palette, with CJK from wqy-microhei. +# The Chinese installer's console: the VT's Tokyo Night palette, with Noto Sans Mono CJK from the offline mirror. [main] -font=JetBrains Mono:size=13,WenQuanYi Micro Hei Mono:size=13 +font=Noto Sans Mono CJK SC:size=13 [colors-dark] background=1a1b26 diff --git a/test/unit/install-text-zh-test.sh b/test/unit/install-text-zh-test.sh index b7b8bd5..da38e40 100644 --- a/test/unit/install-text-zh-test.sh +++ b/test/unit/install-text-zh-test.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Every installer text needs an OMARCHY_ZH entry, or a China install shows it in English. +# Every installer text needs an OMARCHY_ZH entry, or a Chinese install shows it in English. set -euo pipefail @@ -33,7 +33,7 @@ for text in "${texts[@]}"; do done printf 'ok - every installer and dashboard text has a Chinese entry\n' -for action in "View full log" "Drop to shell" "Reboot" "Power off" "Upload log for support" "Global" "China"; do +for action in "View full log" "Drop to shell" "Reboot" "Power off" "Upload log for support"; do [[ -n ${OMARCHY_ZH[$action]:-} ]] || fail "labels passed through variables have Chinese entries" "missing: $action" done printf 'ok - labels passed through variables have Chinese entries\n'