Switch regions from Setup > Region and show Chinese menu labels under zh_CN
This commit is contained in:
1 parent
56c8344fd2
commit
5f6c803b21
12 files changed
+408
-18
No files matched your search
+42
-7
@@ -1,16 +1,51 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Show the region this machine is set up for
|
||||
# omarchy:summary=Show or switch the region this machine is set up for
|
||||
# omarchy:args=[global|china]
|
||||
# omarchy:examples=omarchy region | omarchy region china
|
||||
# omarchy:requires-sudo=true
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
region_file=/etc/omarchy/region
|
||||
|
||||
if [[ ! -e $region_file ]]; then
|
||||
echo "Global"
|
||||
elif [[ $(<"$region_file") == "china" ]]; then
|
||||
echo "China"
|
||||
else
|
||||
echo "Unknown region in $region_file: $(<"$region_file")" >&2
|
||||
if (($# == 0)); then
|
||||
if [[ ! -e $region_file ]]; then
|
||||
echo "Global"
|
||||
elif [[ $(<"$region_file") == "china" ]]; then
|
||||
echo "China"
|
||||
else
|
||||
echo "Unknown region in $region_file: $(<"$region_file")" >&2
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ $1 != "global" && $1 != "china" ]]; then
|
||||
echo "Usage: omarchy-region [global|china]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
pacman_files=(/etc/pacman.conf /etc/pacman.d/mirrorlist)
|
||||
|
||||
if [[ $1 == "china" ]]; then
|
||||
for file in "${pacman_files[@]}"; do
|
||||
if ! grep -q '^Server = https://[a-z-]*\.omarchy\.cn/' "$file"; then
|
||||
sudo sed -i -f "$OMARCHY_PATH/default/region/china/pacman.sed" "$file"
|
||||
fi
|
||||
done
|
||||
echo "Package mirrors -> .cn first, .org after"
|
||||
sudo pacman -Sy
|
||||
sudo env OMARCHY_REGION=china OMARCHY_PATH="$OMARCHY_PATH" bash -e "$OMARCHY_PATH/install/config/region.sh"
|
||||
if [[ ! -f $HOME/.local/share/fcitx5/rime/rime_ice.schema.yaml ]]; then
|
||||
rime-ice-installer --yes
|
||||
fi
|
||||
else
|
||||
sudo sed -i '/^Server = https:\/\/[a-z-]*\.omarchy\.cn\//d' "${pacman_files[@]}"
|
||||
echo "Package mirrors -> .org only"
|
||||
sudo pacman -Sy
|
||||
sudo env OMARCHY_REGION=global OMARCHY_PATH="$OMARCHY_PATH" bash -e "$OMARCHY_PATH/install/config/region.sh"
|
||||
omarchy-setup-claude-api --remove
|
||||
fi
|
||||
|
||||
echo "Region set to ${1^}. Log out and back in to switch the language and developer mirrors."
|
||||
@@ -176,6 +176,9 @@
|
||||
"setup.default.editor.helix": {"icon":"","label":"Helix","checked":"[[ \"$(omarchy-default-editor)\" == \"helix\" ]]","action":"omarchy-default-editor helix"},
|
||||
"setup.default.editor.vim": {"icon":"","label":"Vim","checked":"[[ \"$(omarchy-default-editor)\" == \"vim\" ]]","action":"omarchy-default-editor vim"},
|
||||
"setup.default.editor.emacs": {"icon":" ","label":"Emacs","checked":"[[ \"$(omarchy-default-editor)\" == \"emacs\" ]]","action":"omarchy-default-editor emacs"},
|
||||
"setup.region": {"icon":"","label":"Region"},
|
||||
"setup.region.global": {"icon":"","label":"Global","checked":"[[ \"$(omarchy-region)\" == \"Global\" ]]","action":"omarchy-launch-floating-terminal-with-presentation 'omarchy-region global'"},
|
||||
"setup.region.china": {"icon":"","label":"China","checked":"[[ \"$(omarchy-region)\" == \"China\" ]]","action":"omarchy-launch-floating-terminal-with-presentation 'omarchy-region china'"},
|
||||
"setup.plugin": {"icon":"","label":"Plugins","aliases":["plugin","plugins"]},
|
||||
"setup.plugin.enable": {"icon":"","label":"Enable Plugin","action":"omarchy-menu-plugin enable"},
|
||||
"setup.plugin.disable": {"icon":"","label":"Disable Plugin","action":"omarchy-menu-plugin disable"},
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
// Chinese menu labels, overlaid on omarchy-menu.jsonc when LANG is zh_CN.
|
||||
{
|
||||
"apps": {"label":"应用"},
|
||||
"learn": {"label":"学习"},
|
||||
"trigger": {"label":"触发"},
|
||||
"style": {"label":"风格"},
|
||||
"setup": {"label":"设置"},
|
||||
"install": {"label":"安装"},
|
||||
"remove": {"label":"移除"},
|
||||
"update": {"label":"更新"},
|
||||
"about": {"label":"关于"},
|
||||
"system": {"label":"系统"},
|
||||
"system.screensaver": {"label":"屏保"},
|
||||
"system.lock": {"label":"锁屏"},
|
||||
"system.suspend": {"label":"睡眠"},
|
||||
"system.hibernate": {"label":"休眠"},
|
||||
"system.logout": {"label":"注销"},
|
||||
"system.reboot": {"label":"重启"},
|
||||
"system.shutdown": {"label":"关机"},
|
||||
"learn.keybindings": {"label":"快捷键"},
|
||||
"learn.omarchy": {"label":"Omarchy 手册"},
|
||||
"learn.community": {"label":"社区"},
|
||||
"trigger.emoji": {"label":"表情"},
|
||||
"trigger.reminder": {"label":"提醒"},
|
||||
"trigger.capture": {"label":"截取"},
|
||||
"trigger.capture.screenshot": {"label":"截图"},
|
||||
"trigger.capture.screenrecord.stop": {"label":"停止录屏"},
|
||||
"trigger.capture.screenrecord": {"label":"录屏"},
|
||||
"trigger.capture.text": {"label":"OCR 取字"},
|
||||
"trigger.capture.qr": {"label":"二维码"},
|
||||
"trigger.capture.color": {"label":"取色"},
|
||||
"trigger.capture.screenrecord.no-audio": {"label":"无音频"},
|
||||
"trigger.capture.screenrecord.desktop-audio": {"label":"含桌面音频"},
|
||||
"trigger.capture.screenrecord.microphone": {"label":"含桌面与麦克风音频"},
|
||||
"trigger.capture.screenrecord.webcam": {"label":"含桌面、麦克风与摄像头"},
|
||||
"trigger.transcode": {"label":"转码"},
|
||||
"trigger.share": {"label":"分享"},
|
||||
"trigger.toggle": {"label":"开关"},
|
||||
"trigger.hardware": {"label":"硬件"},
|
||||
"trigger.tests": {"label":"测速"},
|
||||
"trigger.hardware.laptop-display": {"label":"笔记本屏幕"},
|
||||
"trigger.hardware.mirror-display": {"label":"镜像显示"},
|
||||
"trigger.hardware.hybrid-gpu": {"label":"混合显卡"},
|
||||
"trigger.hardware.touchpad": {"label":"触控板"},
|
||||
"trigger.hardware.touchpad-haptics": {"label":"触控板振动"},
|
||||
"trigger.hardware.touchpad-haptics.low": {"label":"低"},
|
||||
"trigger.hardware.touchpad-haptics.mid": {"label":"中"},
|
||||
"trigger.hardware.touchpad-haptics.high": {"label":"高"},
|
||||
"trigger.hardware.touchscreen": {"label":"触摸屏"},
|
||||
"trigger.reminder.set": {"label":"设一个提醒"},
|
||||
"trigger.reminder.show": {"label":"查看全部"},
|
||||
"trigger.reminder.clear": {"label":"清除全部"},
|
||||
"trigger.share.clipboard": {"label":"剪贴板"},
|
||||
"trigger.share.file": {"label":"文件"},
|
||||
"trigger.share.folder": {"label":"文件夹"},
|
||||
"trigger.share.receive": {"label":"接收"},
|
||||
"trigger.toggle.idle-lock": {"label":"保持唤醒"},
|
||||
"trigger.toggle.notifications": {"label":"通知"},
|
||||
"trigger.toggle.crash-capture": {"label":"崩溃捕获"},
|
||||
"trigger.toggle.screensaver": {"label":"屏保"},
|
||||
"trigger.toggle.nightlight": {"label":"夜间模式"},
|
||||
"trigger.toggle.top-bar": {"label":"菜单栏"},
|
||||
"trigger.toggle.battery-percentage": {"label":"电量百分比"},
|
||||
"trigger.toggle.workspace-layout": {"label":"工作区布局"},
|
||||
"trigger.toggle.window-gaps": {"label":"窗口间距"},
|
||||
"trigger.toggle.one-window-ratio": {"label":"单窗口比例"},
|
||||
"trigger.tests.network-speedtest": {"label":"网络测速"},
|
||||
"trigger.tests.disk-speedtest": {"label":"磁盘测速"},
|
||||
"style.theme": {"label":"主题"},
|
||||
"style.background": {"label":"壁纸"},
|
||||
"style.unlock": {"label":"解锁画面"},
|
||||
"style.font": {"label":"字体"},
|
||||
"style.bar": {"label":"菜单栏"},
|
||||
"style.bar.position": {"label":"位置"},
|
||||
"style.bar.transparency": {"label":"透明"},
|
||||
"style.screensaver": {"label":"屏保"},
|
||||
"style.about": {"label":"关于"},
|
||||
"style.bar.position.top": {"label":"顶部"},
|
||||
"style.bar.position.bottom": {"label":"底部"},
|
||||
"style.bar.position.left": {"label":"左侧"},
|
||||
"style.bar.position.right": {"label":"右侧"},
|
||||
"style.about.text": {"label":"编辑文字"},
|
||||
"style.about.image": {"label":"取自图片"},
|
||||
"style.about.default": {"label":"恢复默认"},
|
||||
"style.screensaver.text": {"label":"编辑文字"},
|
||||
"style.screensaver.image": {"label":"取自图片"},
|
||||
"style.screensaver.default": {"label":"恢复默认"},
|
||||
"setup.monitors": {"label":"显示器"},
|
||||
"setup.keybindings": {"label":"快捷键"},
|
||||
"setup.input": {"label":"输入设备"},
|
||||
"setup.network": {"label":"网络"},
|
||||
"setup.network.dns.custom": {"label":"自定义"},
|
||||
"setup.network.qr": {"label":"二维码"},
|
||||
"setup.default": {"label":"默认程序"},
|
||||
"setup.default.agent": {"title":"默认 Agent"},
|
||||
"setup.default.browser": {"label":"浏览器","title":"默认浏览器"},
|
||||
"setup.default.terminal": {"label":"终端","title":"默认终端"},
|
||||
"setup.default.editor": {"label":"编辑器","title":"默认编辑器"},
|
||||
"setup.plugin": {"label":"插件"},
|
||||
"setup.plugin.enable": {"label":"启用插件"},
|
||||
"setup.plugin.disable": {"label":"停用插件"},
|
||||
"setup.plugin.add": {"label":"添加插件"},
|
||||
"setup.plugin.clone": {"label":"克隆插件"},
|
||||
"setup.plugin.remove": {"label":"移除插件"},
|
||||
"setup.security": {"label":"安全"},
|
||||
"setup.config": {"label":"配置"},
|
||||
"setup.security.fingerprint": {"label":"指纹"},
|
||||
"setup.security.passwordless-sudo": {"label":"免密 sudo"},
|
||||
"setup.security.sudoless-docker": {"label":"免 sudo Docker"},
|
||||
"setup.direct-boot": {"label":"直接启动"},
|
||||
"setup.reset": {"label":"恢复出厂设置"},
|
||||
"install.package": {"label":"软件包"},
|
||||
"install.service": {"label":"服务"},
|
||||
"install.development": {"label":"开发环境"},
|
||||
"install.editor": {"label":"编辑器"},
|
||||
"install.style": {"label":"风格"},
|
||||
"install.style.theme": {"label":"主题"},
|
||||
"install.style.background": {"label":"壁纸"},
|
||||
"install.style.font": {"label":"字体"},
|
||||
"install.gaming": {"label":"游戏"},
|
||||
"install.browser": {"label":"浏览器"},
|
||||
"install.webapp": {"label":"网页应用"},
|
||||
"install.terminal": {"label":"终端"},
|
||||
"install.preinstalls": {"label":"预装应用"},
|
||||
"install.service.chromium-account": {"label":"Chromium 账号"},
|
||||
"install.ai.dictation": {"label":"语音听写"},
|
||||
"install.gaming.xbox-cloud": {"label":"Xbox 云游戏"},
|
||||
"install.gaming.xbox-controllers": {"label":"Xbox 手柄"},
|
||||
"install.gaming.retro-launcher": {"label":"RetroArch 启动器"},
|
||||
"install.development.docker-dbs": {"label":"Docker 数据库"},
|
||||
"remove.package": {"label":"软件包"},
|
||||
"remove.ai": {"title":"移除"},
|
||||
"remove.service": {"label":"服务","title":"移除"},
|
||||
"remove.development": {"label":"开发环境","title":"移除"},
|
||||
"remove.theme": {"label":"主题"},
|
||||
"remove.gaming": {"label":"游戏","title":"移除"},
|
||||
"remove.browser": {"label":"浏览器","title":"移除"},
|
||||
"remove.webapp": {"label":"网页应用"},
|
||||
"remove.preinstalls": {"label":"预装应用"},
|
||||
"remove.security": {"label":"安全","title":"移除"},
|
||||
"remove.security.fingerprint": {"label":"指纹"},
|
||||
"remove.security.sudoless-docker": {"label":"免 sudo Docker"},
|
||||
"remove.ai.dictation": {"label":"语音听写"},
|
||||
"remove.gaming.xbox-cloud": {"label":"Xbox 云游戏"},
|
||||
"remove.gaming.xbox-controllers": {"label":"Xbox 手柄 ()"},
|
||||
"remove.development.javascript": {"title":"移除"},
|
||||
"remove.development.php": {"title":"移除"},
|
||||
"remove.development.elixir": {"title":"移除"},
|
||||
"update.channel": {"label":"通道"},
|
||||
"update.config": {"label":"配置","title":"重置为默认"},
|
||||
"update.themes": {"label":"附加主题"},
|
||||
"update.process": {"label":"进程","title":"重启"},
|
||||
"update.hardware": {"label":"硬件","title":"重启"},
|
||||
"update.firmware": {"label":"固件"},
|
||||
"update.password": {"label":"密码"},
|
||||
"update.timezone": {"label":"时区"},
|
||||
"update.time": {"label":"时间"},
|
||||
"update.hardware.audio": {"label":"音频"},
|
||||
"update.hardware.bluetooth": {"label":"蓝牙"},
|
||||
"update.hardware.trackpad": {"label":"触控板"},
|
||||
"update.password.drive": {"label":"磁盘加密"},
|
||||
"update.password.user": {"label":"用户"},
|
||||
"trigger.toggle.animations": {"label":"动画"},
|
||||
"trigger.toggle.theme-sync": {"label":"Herdr 主题同步"},
|
||||
"setup.region": {"label":"地区"},
|
||||
"setup.region.global": {"label":"全球"},
|
||||
"setup.region.china": {"label":"中国"},
|
||||
"install.china": {"label":"国内应用"},
|
||||
"install.china.wechat": {"label":"微信"},
|
||||
"install.china.feishu": {"label":"飞书"},
|
||||
"install.china.dingtalk": {"label":"钉钉"},
|
||||
"install.china.wemeet": {"label":"腾讯会议"},
|
||||
"install.china.tencent-docs": {"label":"腾讯文档"},
|
||||
"install.china.yuque": {"label":"语雀"},
|
||||
"install.china.shimo": {"label":"石墨文档"},
|
||||
"update.channel.stable": {"label":"稳定版"},
|
||||
"update.channel.rc": {"label":"候选版"},
|
||||
"update.channel.edge": {"label":"尝鲜版"},
|
||||
"update.channel.dev": {"label":"开发版"},
|
||||
}
|
||||
@@ -56,6 +56,8 @@ or re-icon a row without re-declaring its action, and an overridden entry
|
||||
keeps its original position in the list. New ids append. A `root` entry is
|
||||
injected if neither file declares one.
|
||||
|
||||
When `LANG` starts with `zh_CN`, `default/omarchy/omarchy-menu.zh-cn.jsonc` is merged between the defaults and the user extension. It only retitles shipped ids, so a user extension still wins, and the language follows `/etc/locale.conf` instead of any file `omarchy update` rewrites.
|
||||
|
||||
The sample extension at `config/omarchy/extensions/omarchy-menu.jsonc`
|
||||
(refreshed into `~/.config/`) documents the format in its header and ships
|
||||
only comments, so the default state adds nothing.
|
||||
|
||||
@@ -7,6 +7,7 @@ china_links=(
|
||||
case ${OMARCHY_REGION:-global} in
|
||||
global)
|
||||
rm -f /etc/omarchy/region
|
||||
sed -i 's/^LANG=zh_CN\.UTF-8$/LANG=en_US.UTF-8/' /etc/locale.conf
|
||||
for link in "${china_links[@]}"; do
|
||||
read -r _ target <<<"$link"
|
||||
if [[ -L $target && $(readlink "$target") == */default/region/china/* ]]; then
|
||||
@@ -27,6 +28,13 @@ china)
|
||||
ln -sfn "$OMARCHY_PATH/default/region/china/$source" "$target"
|
||||
done
|
||||
omarchy-pkg-add fcitx5-configtool fcitx5-rime librime opencc rime-ice-installer
|
||||
sed -i 's/^#\(zh_CN\.UTF-8 UTF-8\)/\1/' /etc/locale.gen
|
||||
locale-gen
|
||||
if grep -q '^LANG=' /etc/locale.conf; then
|
||||
sed -i 's/^LANG=.*/LANG=zh_CN.UTF-8/' /etc/locale.conf
|
||||
else
|
||||
echo LANG=zh_CN.UTF-8 >>/etc/locale.conf
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Unknown OMARCHY_REGION: $OMARCHY_REGION" >&2
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ Progress source of truth for the `omarchycn` branches of `omarchy`, `omarchy-iso
|
||||
- [x] T4 CJK fontconfig fix (PRD 4): rebuild PR 9693 on the current base
|
||||
- [x] T5 AI (PRD 5): Dim and Kimi Code for every region (rebuild PR 9694), Claude Code third-party provider setup shown only in China
|
||||
- [x] T6 Developer mirrors (PRD 6): npm, PyPI/uv, Go, rustup, crates.io, RubyGems, Maven via system drop-ins under `default/region/china/`
|
||||
- [ ] T7 China software (PRD 7): Install menu entry shown only in China
|
||||
- [x] T7 China software (PRD 7): Install menu entry shown only in China
|
||||
- [ ] T8 Region switching and Chinese UI (PRD 8): `omarchy-region china|global`, Setup > Region, locale, Chinese menu overlay chosen by `LANG`
|
||||
- [ ] T9 Logo (PRD 9): stock Omarchy logo everywhere
|
||||
- [ ] T10 Docs: `AGENTS.md`, manual
|
||||
|
||||
@@ -37,6 +37,7 @@ Item {
|
||||
|
||||
function refresh() {
|
||||
defaultMenuFile.reload()
|
||||
localeMenuFile.reload()
|
||||
userMenuFile.reload()
|
||||
return "ok"
|
||||
}
|
||||
@@ -49,7 +50,9 @@ Item {
|
||||
// path doesn't have to shell out to bash + jq on every open.
|
||||
property string defaultMenuPath: omarchyPath + "/default/omarchy/omarchy-menu.jsonc"
|
||||
property string userMenuPath: Quickshell.env("HOME") + "/.config/omarchy/extensions/omarchy-menu.jsonc"
|
||||
property string localeMenuPath: (Quickshell.env("LANG") || "").startsWith("zh_CN") ? omarchyPath + "/default/omarchy/omarchy-menu.zh-cn.jsonc" : ""
|
||||
property var defaultMenuItems: []
|
||||
property var localeMenuItems: []
|
||||
property var userMenuItems: []
|
||||
property bool opened: false
|
||||
property string mode: "menu"
|
||||
@@ -247,7 +250,7 @@ Item {
|
||||
// on a per-key basis (so the user can tweak label/icon/action without
|
||||
// re-declaring the whole row).
|
||||
function rebuildItemsFromSources() {
|
||||
var mergedMenu = MenuModel.mergeMenuSources(root.defaultMenuItems, root.userMenuItems)
|
||||
var mergedMenu = MenuModel.mergeMenuSources(root.defaultMenuItems, root.localeMenuItems.concat(root.userMenuItems))
|
||||
root.providerRevision += 1
|
||||
root.providersLoaded = ({})
|
||||
root.providerQueue = []
|
||||
@@ -974,6 +977,16 @@ Item {
|
||||
onFileChanged: reload()
|
||||
}
|
||||
|
||||
FileView {
|
||||
id: localeMenuFile
|
||||
path: root.localeMenuPath
|
||||
watchChanges: true
|
||||
printErrors: false
|
||||
onLoaded: { root.localeMenuItems = root.parseMenuJsonc(text()); root.rebuildItemsFromSources() }
|
||||
onLoadFailed: { root.localeMenuItems = []; root.rebuildItemsFromSources() }
|
||||
onFileChanged: reload()
|
||||
}
|
||||
|
||||
FileView {
|
||||
id: userMenuFile
|
||||
path: root.userMenuPath
|
||||
|
||||
@@ -58,7 +58,9 @@ function parseMenuJsonc(raw) {
|
||||
for (var id in source) {
|
||||
var entry = source[id]
|
||||
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue
|
||||
out.push(normalizeItem(id, entry))
|
||||
var item = normalizeItem(id, entry)
|
||||
item.declared = Object.keys(entry)
|
||||
out.push(item)
|
||||
}
|
||||
return out
|
||||
}
|
||||
@@ -74,11 +76,24 @@ function mergeMenuSources(defaultItems, userItems) {
|
||||
var entry = src[i]
|
||||
if (!entry || !entry.id) continue
|
||||
if (!nextItems[entry.id]) nextOrder.push(entry.id)
|
||||
var prior = nextItems[entry.id] || {}
|
||||
var prior = nextItems[entry.id]
|
||||
var merged = {}
|
||||
for (var k in prior) merged[k] = prior[k]
|
||||
for (var k2 in entry) merged[k2] = entry[k2]
|
||||
// An override replaces only the fields its file declared.
|
||||
if (prior && entry.declared) {
|
||||
for (var k in prior) merged[k] = prior[k]
|
||||
for (var d = 0; d < entry.declared.length; d++) {
|
||||
var key = entry.declared[d]
|
||||
if (key in entry) merged[key] = entry[key]
|
||||
}
|
||||
if (entry.declared.indexOf("action") >= 0 || entry.declared.indexOf("target") >= 0)
|
||||
merged.kind = merged.action ? "action" : (merged.target ? "link" : "menu")
|
||||
} else {
|
||||
prior = prior || {}
|
||||
for (var k1 in prior) merged[k1] = prior[k1]
|
||||
for (var k2 in entry) merged[k2] = entry[k2]
|
||||
}
|
||||
merged.id = entry.id
|
||||
delete merged.declared
|
||||
nextItems[entry.id] = merged
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
||||
|
||||
require_command node
|
||||
|
||||
node - "$ROOT" <<'JS'
|
||||
const fs = require('fs')
|
||||
const root = process.argv[2]
|
||||
const model = require(`${root}/shell/plugins/menu/MenuModel.js`)
|
||||
const read = name => model.parseMenuJsonc(fs.readFileSync(`${root}/default/omarchy/${name}`, 'utf8'))
|
||||
const fail = message => { console.error(`not ok - ${message}`); process.exit(1) }
|
||||
|
||||
const defaults = read('omarchy-menu.jsonc')
|
||||
const chinese = read('omarchy-menu.zh-cn.jsonc')
|
||||
const byId = Object.fromEntries(defaults.map(item => [item.id, item]))
|
||||
|
||||
const unknown = chinese.filter(item => !byId[item.id]).map(item => item.id)
|
||||
if (unknown.length) fail(`every Chinese label names a shipped menu id: ${unknown}`)
|
||||
const extra = chinese.filter(item => item.declared.some(key => key !== 'label' && key !== 'title')).map(item => item.id)
|
||||
if (extra.length) fail(`the Chinese overlay only retitles rows: ${extra}`)
|
||||
console.log('ok - the Chinese overlay only retitles shipped menu rows')
|
||||
|
||||
const user = model.parseMenuJsonc('{"system.lock": {"label": "Mine"}}')
|
||||
const merged = model.mergeMenuSources(defaults, chinese.concat(user)).items
|
||||
for (const item of defaults) {
|
||||
const result = merged[item.id]
|
||||
const zh = chinese.find(entry => entry.id === item.id)
|
||||
for (const key of ['action', 'when', 'checked', 'disabled', 'target', 'provider', 'kind', 'icon', 'parent']) {
|
||||
if (JSON.stringify(result[key]) !== JSON.stringify(item[key])) fail(`${item.id} keeps its ${key} under the Chinese overlay`)
|
||||
}
|
||||
if (item.id !== 'system.lock' && zh && zh.declared.includes('label') && result.label !== zh.label) fail(`${item.id} shows its Chinese label`)
|
||||
}
|
||||
if (merged['system.lock'].label !== 'Mine') fail('a user extension still overrides the Chinese label')
|
||||
if (merged['system.reboot'].label !== '重启' || merged['install.china.wechat'].label !== '微信') fail('Chinese labels reach the merged menu')
|
||||
console.log('ok - Chinese labels replace only the label, and user extensions still win')
|
||||
JS
|
||||
|
||||
grep -qF 'root.localeMenuItems.concat(root.userMenuItems)' "$ROOT/shell/plugins/menu/Menu.qml" &&
|
||||
grep -qF 'startsWith("zh_CN") ? omarchyPath + "/default/omarchy/omarchy-menu.zh-cn.jsonc"' "$ROOT/shell/plugins/menu/Menu.qml" ||
|
||||
fail "the menu loads the Chinese overlay under zh_CN, beneath the user extension"
|
||||
pass "the menu loads the Chinese overlay under zh_CN, beneath the user extension"
|
||||
@@ -62,9 +62,10 @@ assertDeepEqual(
|
||||
aliases: ['theme'],
|
||||
when: '',
|
||||
checked: '',
|
||||
disabled: ''
|
||||
disabled: '',
|
||||
declared: ['label', 'aliases', 'description', 'action']
|
||||
},
|
||||
'menu normalizes parsed items'
|
||||
'menu normalizes parsed items and records what the file declared'
|
||||
)
|
||||
|
||||
const user = [
|
||||
@@ -76,6 +77,16 @@ assertEqual(merged.items['style.theme'].label, 'Theme picker', 'menu user entrie
|
||||
assertEqual(merged.items['style.theme'].order, 2, 'menu preserves original order on override')
|
||||
assert(merged.items.root, 'menu injects root when merging sources')
|
||||
|
||||
const retitled = menu.mergeMenuSources(
|
||||
menu.parseMenuJsonc('{"apps": {"icon":"A","label":"Apps","provider":"apps"}, "apps.go": {"label":"Go","action":"run-go"}}'),
|
||||
menu.parseMenuJsonc('{"apps": {"label":"应用"}, "apps.go": {"label":"出发"}}')
|
||||
)
|
||||
assertEqual(retitled.items['apps'].provider, 'apps', 'menu keeps the provider when a user entry only retitles')
|
||||
assertEqual(retitled.items['apps'].icon, 'A', 'menu keeps the icon when a user entry only retitles')
|
||||
assertEqual(retitled.items['apps.go'].action, 'run-go', 'menu keeps the action when a user entry only retitles')
|
||||
assertEqual(retitled.items['apps.go'].kind, 'action', 'menu keeps the kind when a user entry only retitles')
|
||||
assertEqual(retitled.items['apps.go'].label, '出发', 'menu applies the user retitle')
|
||||
|
||||
assertEqual(menu.slugify('Power Saver!'), 'power-saver', 'menu slugifies provider rows')
|
||||
assertEqual(menu.pathFor(merged.items, 'style.theme'), 'Style › Theme picker', 'menu builds item paths')
|
||||
assertEqual(menu.parentPathFor(merged.items, 'style.theme'), 'Style', 'menu builds parent paths')
|
||||
@@ -286,6 +297,14 @@ assert(
|
||||
'menu always exposes every supported browser, terminal, and editor under Defaults'
|
||||
)
|
||||
assert(!defaultById['install.ai.crush'], 'menu removes Crush from Install > AI')
|
||||
const regionEntries = defaultItems.filter(item => item.parent === 'setup.region')
|
||||
assert(
|
||||
regionEntries.map(item => item.label).join('\0') === 'Global\0China'
|
||||
&& regionEntries.every(item => item.checked.includes(`== \"${item.label}\"`) && !item.when)
|
||||
&& defaultById['setup.region.global'].action.includes('omarchy-region global')
|
||||
&& defaultById['setup.region.china'].action.includes('omarchy-region china'),
|
||||
'menu offers Global and China under Setup > Region'
|
||||
)
|
||||
// Software you already have keeps its place in Install, dimmed rather than
|
||||
// dropped, so the list reads as a catalog of what Omarchy can install.
|
||||
// Chromium Account is the sole Install row with anything left to hide for, so
|
||||
|
||||
Executable
+60
@@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
||||
|
||||
test_tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$test_tmp"' EXIT
|
||||
|
||||
root="$test_tmp/root" sandbox="$test_tmp/omarchy" calls="$test_tmp/calls"
|
||||
mkdir -p "$root/etc/pacman.d" "$sandbox/bin" "$sandbox/install/config" "$sandbox/default/region" "$test_tmp/bin" "$test_tmp/home"
|
||||
cp -r "$ROOT/default/region/china" "$sandbox/default/region/"
|
||||
rewrite() { sed -e "s|/etc/|$root/etc/|g" -e "s| /\\.cargo/| $root/.cargo/|g" "$1" >"$2"; chmod +x "$2"; }
|
||||
rewrite "$ROOT/install/config/region.sh" "$sandbox/install/config/region.sh"
|
||||
rewrite "$ROOT/bin/omarchy-region" "$sandbox/bin/omarchy-region"
|
||||
|
||||
for command in pacman omarchy-pkg-add locale-gen rime-ice-installer omarchy-setup-claude-api; do
|
||||
printf '#!/bin/bash\necho "%s $*" >>"%s"\n' "$command" "$calls" >"$test_tmp/bin/$command"
|
||||
done
|
||||
printf '#!/bin/bash\n[[ $1 == env ]] && shift\nexec env "$@"\n' >"$test_tmp/bin/sudo"
|
||||
chmod +x "$test_tmp/bin"/*
|
||||
export PATH="$test_tmp/bin:$sandbox/bin:$PATH" OMARCHY_PATH="$sandbox" HOME="$test_tmp/home"
|
||||
|
||||
cp "$ROOT/default/pacman/pacman-stable.conf" "$root/etc/pacman.conf"
|
||||
cp "$ROOT/default/pacman/mirrorlist-stable" "$root/etc/pacman.d/mirrorlist"
|
||||
printf '#zh_CN.UTF-8 UTF-8\nen_US.UTF-8 UTF-8\n' >"$root/etc/locale.gen"
|
||||
printf 'LANG=en_US.UTF-8\n' >"$root/etc/locale.conf"
|
||||
|
||||
china_conf=$(sed -f "$ROOT/default/region/china/pacman.sed" "$ROOT/default/pacman/pacman-stable.conf")
|
||||
china_mirrors=$(sed -f "$ROOT/default/region/china/pacman.sed" "$ROOT/default/pacman/mirrorlist-stable")
|
||||
|
||||
omarchy-region china >/dev/null
|
||||
[[ $(<"$root/etc/pacman.conf") == "$china_conf" && $(<"$root/etc/pacman.d/mirrorlist") == "$china_mirrors" ]] ||
|
||||
fail "switching to China lists the .cn mirrors first"
|
||||
[[ $(omarchy-region) == "China" && $(<"$root/etc/locale.conf") == "LANG=zh_CN.UTF-8" ]] || fail "switching to China records it and sets the language"
|
||||
[[ $(<"$calls") == $'pacman -Sy\nomarchy-pkg-add fcitx5-configtool fcitx5-rime librime opencc rime-ice-installer\nlocale-gen \nrime-ice-installer --yes' ]] ||
|
||||
fail "China syncs the .cn databases before installing Rime, then sets Rime Ice up" "$(<"$calls")"
|
||||
pass "switching to China sets mirrors, language and Rime Ice"
|
||||
|
||||
: >"$calls"
|
||||
mkdir -p "$HOME/.local/share/fcitx5/rime" && touch "$HOME/.local/share/fcitx5/rime/rime_ice.schema.yaml"
|
||||
omarchy-region china >/dev/null
|
||||
[[ $(<"$root/etc/pacman.conf") == "$china_conf" && $(<"$root/etc/pacman.d/mirrorlist") == "$china_mirrors" ]] ||
|
||||
fail "switching to China twice adds no second .cn line"
|
||||
grep -q '^rime-ice-installer' "$calls" && fail "an existing Rime Ice setup is not redone"
|
||||
pass "switching to China again changes nothing it already did"
|
||||
|
||||
: >"$calls"
|
||||
omarchy-region global >/dev/null
|
||||
[[ $(<"$root/etc/pacman.conf") == "$(<"$ROOT/default/pacman/pacman-stable.conf")" && $(<"$root/etc/pacman.d/mirrorlist") == "$(<"$ROOT/default/pacman/mirrorlist-stable")" ]] ||
|
||||
fail "switching to Global drops exactly the .cn mirrors"
|
||||
[[ $(omarchy-region) == "Global" && $(<"$root/etc/locale.conf") == "LANG=en_US.UTF-8" ]] || fail "switching to Global records it and restores English"
|
||||
[[ $(<"$calls") == $'pacman -Sy\nomarchy-setup-claude-api --remove' ]] || fail "Global removes the Claude Code third-party API and keeps Rime" "$(<"$calls")"
|
||||
[[ -f $HOME/.local/share/fcitx5/rime/rime_ice.schema.yaml ]] || fail "Global keeps the input method"
|
||||
pass "switching to Global restores mirrors and language, keeps Rime, removes the Claude API setup"
|
||||
|
||||
if output=$(omarchy-region mars 2>&1); then
|
||||
fail "an unknown region is refused" "$output"
|
||||
fi
|
||||
pass "an unknown region is refused"
|
||||
@@ -58,7 +58,7 @@ pass "an unknown region fails and names the file and value"
|
||||
stub_bin="$test_tmp/bin"
|
||||
calls="$test_tmp/calls"
|
||||
mkdir -p "$stub_bin"
|
||||
for command in omarchy-pkg-add rime-ice-installer; do
|
||||
for command in omarchy-pkg-add rime-ice-installer locale-gen; do
|
||||
printf '#!/bin/bash\necho "%s $*" >>"%s"\n' "$command" "$calls" >"$stub_bin/$command"
|
||||
done
|
||||
printf '#!/bin/bash\necho "$STUB_REGION"\n' >"$stub_bin/omarchy-region"
|
||||
@@ -69,12 +69,17 @@ region_setup="$test_tmp/region.sh"
|
||||
root="$test_tmp/root"
|
||||
sed -e "s|/etc/|$root/etc/|g" -e "s| /\.cargo/| $root/.cargo/|g" "$ROOT/install/config/region.sh" >"$region_setup"
|
||||
export OMARCHY_PATH="$ROOT"
|
||||
mkdir -p "$root/etc"
|
||||
printf '#zh_CN.UTF-8 UTF-8\nen_US.UTF-8 UTF-8\n' >"$root/etc/locale.gen"
|
||||
printf 'LANG=en_US.UTF-8\nLC_TIME=en_DK.UTF-8\n' >"$root/etc/locale.conf"
|
||||
|
||||
: >"$calls"
|
||||
OMARCHY_REGION=china bash -e "$region_setup"
|
||||
[[ $(<"$root/etc/omarchy/region") == "china" ]] || fail "install records the China region"
|
||||
[[ $(<"$calls") == "omarchy-pkg-add fcitx5-configtool fcitx5-rime librime opencc rime-ice-installer" ]] ||
|
||||
fail "China installs the Rime input method packages" "$(<"$calls")"
|
||||
[[ $(<"$calls") == $'omarchy-pkg-add fcitx5-configtool fcitx5-rime librime opencc rime-ice-installer\nlocale-gen ' ]] ||
|
||||
fail "China installs the Rime input method packages and generates the Chinese locale" "$(<"$calls")"
|
||||
[[ $(<"$root/etc/locale.gen") == $'zh_CN.UTF-8 UTF-8\nen_US.UTF-8 UTF-8' ]] || fail "China enables zh_CN in locale.gen"
|
||||
[[ $(<"$root/etc/locale.conf") == $'LANG=zh_CN.UTF-8\nLC_TIME=en_DK.UTF-8' ]] || fail "China sets LANG and keeps other locale settings" "$(<"$root/etc/locale.conf")"
|
||||
for package in fcitx5-configtool fcitx5-rime librime opencc rime-ice-installer; do
|
||||
grep -qx "$package" "$ROOT/install/omarchy-other.packages" || fail "the ISO mirror carries $package"
|
||||
done
|
||||
@@ -90,6 +95,12 @@ pass "China links the developer mirror drop-ins"
|
||||
OMARCHY_REGION=global bash -e "$region_setup"
|
||||
[[ ! -e $root/etc/omarchy/region ]] || fail "install records Global by leaving no region file"
|
||||
[[ ! -s $calls ]] || fail "Global installs no input method packages" "$(<"$calls")"
|
||||
[[ $(<"$root/etc/locale.conf") == $'LANG=en_US.UTF-8\nLC_TIME=en_DK.UTF-8' ]] || fail "Global turns a Chinese LANG back to English" "$(<"$root/etc/locale.conf")"
|
||||
printf 'LANG=de_DE.UTF-8\n' >"$root/etc/locale.conf"
|
||||
OMARCHY_REGION=global bash -e "$region_setup"
|
||||
[[ $(<"$root/etc/locale.conf") == "LANG=de_DE.UTF-8" ]] || fail "Global leaves a language China did not set"
|
||||
printf 'LANG=en_US.UTF-8\n' >"$root/etc/locale.conf"
|
||||
pass "the region sets the language and Global only undoes Chinese"
|
||||
[[ ! -e $root/etc/environment.d/90-omarchy-china.conf && ! -e $root/.cargo/config.toml && ! -e $root/etc/gemrc ]] ||
|
||||
fail "Global removes the developer mirror drop-ins"
|
||||
pass "Global removes the developer mirror drop-ins"
|
||||
|
||||
Reference in new issue
Block a user