Skip to content

Commit 46ffa10

Browse files
chenchaoyiclaude
andauthored
fix(helper): localise TCC prompts via lproj/InfoPlist.strings (#43)
User report: the two macOS TCC permission popups looked inconsistent on a zh-locale machine — the Location prompt showed "谛听 · 天耳" (Chinese) while the Bluetooth prompt showed "diting-tianer.app" (English-looking bundle filename), and both prompt bodies were always English even for zh users. Root cause: the bundle had `CFBundleDisplayName = "谛听 · 天耳"` set at the top level of Info.plist but no localised InfoPlist.strings overrides. macOS picks the TCC prompt's header from different fields per category (Location reads CFBundleDisplayName, Bluetooth falls back to the bundle's URL filename), and both prompt bodies come straight from the NSLocationUsageDescription / NSBluetoothAlwaysUsageDescription plist keys — which were English-only. Fix: proper locale-aware InfoPlist.strings. - New helper/Resources/en.lproj/InfoPlist.strings with English overrides for CFBundleDisplayName / CFBundleName / NSLocation* / NSBluetoothAlwaysUsageDescription - New helper/Resources/zh-Hans.lproj/InfoPlist.strings with the Chinese equivalents (display name "谛听 · 天耳", prompt bodies translated) - Info.plist top-level CFBundleName / CFBundleDisplayName unified to "diting · tianer" (English fallback for non-lproj-aware locales); the previous split between CFBundleName=diting-tianer and CFBundleDisplayName=谛听 was what created the prompt inconsistency in the first place - Info.plist declares CFBundleLocalizations [en, zh-Hans] for older macOS releases that don't auto-discover lproj dirs - helper/build.sh copies the Resources/*.lproj tree into the assembled bundle Both .strings files pass `plutil -lint`; the bundle rebuilds cleanly with no errors. zh-locale TCC prompts on v1.0.4 should now show consistent Chinese display name + Chinese body in both the Location and Bluetooth dialogs. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent bea5da2 commit 46ffa10

8 files changed

Lines changed: 127 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,37 @@ the project follows [Semantic Versioning](https://semver.org/) where
99
practical. The leading `v0.x` line is allowed to break minor
1010
behaviours between releases.
1111

12+
## [1.0.4] — 2026-05-13
13+
14+
User reported macOS's TCC permission prompts were inconsistent:
15+
the Location prompt showed "谛听 · 天耳" (Chinese display name)
16+
while the Bluetooth prompt showed "diting-tianer.app" (raw bundle
17+
filename) — and both prompt bodies were always English even for
18+
zh users. macOS picks the TCC prompt's header name from different
19+
fields per category (`CFBundleDisplayName` for Location, the
20+
bundle's URL filename for Bluetooth), and the prompt body comes
21+
straight from the usage-description plist keys.
22+
23+
### Fixed
24+
- **TCC prompts now localise consistently.** Helper bundle ships
25+
`Resources/en.lproj/InfoPlist.strings` and `Resources/zh-Hans.lproj/
26+
InfoPlist.strings` with locale-specific `CFBundleDisplayName`,
27+
`CFBundleName`, and all three usage-description keys
28+
(`NSLocationUsageDescription`,
29+
`NSLocationWhenInUseUsageDescription`,
30+
`NSBluetoothAlwaysUsageDescription`). macOS now picks Chinese
31+
strings for zh users in both the Location and Bluetooth prompt
32+
headers AND bodies. `CFBundleLocalizations` lists both
33+
locales so older macOS releases that don't autodiscover lproj
34+
dirs still pick the right one. `helper/build.sh` copies the
35+
`Resources/*.lproj` tree into the assembled `.app`.
36+
- **Top-level `Info.plist` `CFBundleName` / `CFBundleDisplayName`
37+
unified.** Both keys now default to `diting · tianer` (English
38+
fallback) instead of the previous split where `CFBundleName` was
39+
`diting-tianer` and `CFBundleDisplayName` was `谛听 · 天耳`
40+
the split was what produced the language-inconsistent prompts
41+
in the first place.
42+
1243
## [1.0.3] — 2026-05-13
1344

1445
First end-user-installed release surfaced a long-latent CoreWLAN

docs/zh/CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,33 @@
88
[Semantic Versioning](https://semver.org/)`v0.x` 阶段允许破坏性的次要
99
行为变更。
1010

11+
## [1.0.4] — 2026-05-13
12+
13+
用户反馈 macOS TCC 权限弹窗不一致:定位权限弹窗显示「谛听 · 天耳」
14+
(中文显示名),蓝牙权限弹窗显示「diting-tianer.app」(裸 bundle
15+
文件名);而且两个弹窗的正文都永远是英文,中文用户看不到中文描
16+
述。本质上 macOS 给不同类别的 TCC 弹窗取标题字段的来源不一样
17+
(定位用 `CFBundleDisplayName`,蓝牙用 bundle URL filename),
18+
弹窗正文则直接来自 usage description 字段。
19+
20+
### 修复
21+
- **TCC 弹窗在各语言下保持一致**。Helper bundle 新增
22+
`Resources/en.lproj/InfoPlist.strings`
23+
`Resources/zh-Hans.lproj/InfoPlist.strings`,按当前 locale 提供
24+
`CFBundleDisplayName` / `CFBundleName` 以及三个 usage description
25+
字段(`NSLocationUsageDescription`
26+
`NSLocationWhenInUseUsageDescription`
27+
`NSBluetoothAlwaysUsageDescription`)。zh 用户现在在「定位」和
28+
「蓝牙」两个弹窗里都看到中文标题和中文正文。Info.plist 新增
29+
`CFBundleLocalizations` 列出两种语言,老版本 macOS 不自动扫
30+
lproj 目录也能找到对应翻译。`helper/build.sh` 已经把
31+
`Resources/*.lproj` 整棵树拷进打包好的 .app。
32+
- **`Info.plist` 顶层 `CFBundleName` / `CFBundleDisplayName` 统一**
33+
两个 key 现在都默认是 `diting · tianer`(英文兜底);先前
34+
`CFBundleName``diting-tianer``CFBundleDisplayName`
35+
`谛听 · 天耳` —— 正是这种分裂导致了上面那种语言不一致的 TCC
36+
弹窗组合。
37+
1138
## [1.0.3] — 2026-05-13
1239

1340
第一个真正可被最终用户装出来的 release。装出来之后 `diting` 一直卡

helper/Info.plist

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,26 @@
1111
<key>CFBundleIdentifier</key>
1212
<string>com.chenchaoyi.diting.tianer</string>
1313

14+
<!-- CFBundleName / CFBundleDisplayName here are the English
15+
defaults (fallback for any locale not in our lproj list).
16+
The real per-locale display strings live in
17+
Resources/{en,zh-Hans}.lproj/InfoPlist.strings so macOS
18+
picks the user's preferred language for both the TCC prompt
19+
header AND the prompt body
20+
(NSLocationUsageDescription / NSBluetoothAlwaysUsageDescription).
21+
Older macOS that doesn't honour CFBundleLocalizations still
22+
falls back to these top-level values. -->
1423
<key>CFBundleName</key>
15-
<string>diting-tianer</string>
24+
<string>diting · tianer</string>
1625

1726
<key>CFBundleDisplayName</key>
18-
<string>谛听 · 天耳</string>
27+
<string>diting · tianer</string>
28+
29+
<key>CFBundleLocalizations</key>
30+
<array>
31+
<string>en</string>
32+
<string>zh-Hans</string>
33+
</array>
1934

2035
<key>CFBundlePackageType</key>
2136
<string>APPL</string>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/* English (default) localisation for the helper bundle's Info.plist.
2+
*
3+
* macOS's TCC prompts and the Finder display name read both
4+
* CFBundleDisplayName and the usage descriptions through the
5+
* active locale's lproj. Without this file, English users would
6+
* see the global CFBundleDisplayName ("谛听 · 天耳") even though
7+
* their locale is English — and the prompt bodies are English
8+
* literals living in Info.plist directly.
9+
*
10+
* Keys must match exactly; macOS does NOT fall back to Info.plist
11+
* if a key is missing here.
12+
*/
13+
14+
"CFBundleDisplayName" = "diting · tianer";
15+
"CFBundleName" = "diting · tianer";
16+
17+
"NSLocationUsageDescription" = "diting reads nearby Wi-Fi network names and BSSIDs to label access points and detect roaming. Location data never leaves your machine.";
18+
"NSLocationWhenInUseUsageDescription" = "diting reads nearby Wi-Fi network names and BSSIDs to label access points and detect roaming. Location data never leaves your machine.";
19+
"NSBluetoothAlwaysUsageDescription" = "diting scans nearby BLE advertisements so the TUI can show you what devices are around.";
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* Simplified Chinese localisation for the helper bundle's Info.plist.
2+
*
3+
* Applies when the user's macOS preferred language starts with `zh`
4+
* (zh-Hans, zh-CN, zh-HK with Simplified fallback). macOS shows
5+
* these strings in the TCC prompts (CWNetwork / CBCentralManager
6+
* permission dialogs) and in the Finder / Force Quit dialog.
7+
*
8+
* Keep parity with the EN strings — same fields, equivalent
9+
* meaning. The brand name 谛听 · 天耳 follows the project memory:
10+
* 谛听 (diting) is the family name, 天耳 (tianer) is the helper.
11+
*/
12+
13+
"CFBundleDisplayName" = "谛听 · 天耳";
14+
"CFBundleName" = "谛听 · 天耳";
15+
16+
"NSLocationUsageDescription" = "diting 读取附近 Wi-Fi 网络的 SSID 和 BSSID,用于识别 AP 与漫游事件。位置数据不会离开你的电脑。";
17+
"NSLocationWhenInUseUsageDescription" = "diting 读取附近 Wi-Fi 网络的 SSID 和 BSSID,用于识别 AP 与漫游事件。位置数据不会离开你的电脑。";
18+
"NSBluetoothAlwaysUsageDescription" = "diting 扫描附近 BLE 广播,TUI 才能显示周围的设备。";

helper/build.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ cp Info.plist "$BUNDLE/Contents/Info.plist"
3131
cp "$BIN_PATH" "$BUNDLE/Contents/MacOS/$BIN_NAME"
3232
chmod +x "$BUNDLE/Contents/MacOS/$BIN_NAME"
3333

34+
# Ship per-locale InfoPlist.strings overrides so macOS's TCC
35+
# prompts (Location / Bluetooth) AND the Finder display name pick
36+
# up Chinese strings for zh users instead of the English defaults
37+
# baked into Info.plist. Without these, the user sees one prompt
38+
# with "谛听 · 天耳" (CFBundleDisplayName) and another with
39+
# "diting-tianer.app" (the bundle filename), since macOS uses
40+
# different name sources across TCC prompt categories.
41+
for lproj in Resources/*.lproj; do
42+
if [ -d "$lproj" ]; then
43+
cp -R "$lproj" "$BUNDLE/Contents/Resources/"
44+
fi
45+
done
46+
3447
echo "==> ad-hoc code signing"
3548
# Ad-hoc signature is enough for local use; macOS still recognises the
3649
# bundle as a distinct TCC subject. For distribution, replace `-` with

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "diting"
3-
version = "1.0.3"
3+
version = "1.0.4"
44
description = "macOS terminal listening post for Wi-Fi, BLE, link health, and the RF environment — your Mac hears more than it tells you"
55
readme = "README.md"
66
license = "MIT"

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)