Skip to content

Localize both apps into Simplified Chinese - #308

Open
zkkzkk wants to merge 3 commits into
Saffsanity:mainfrom
zkkzkk:localize-zh-hans
Open

zkkzkk wants to merge 3 commits into
Saffsanity:mainfrom
zkkzkk:localize-zh-hans

Conversation

@zkkzkk

@zkkzkk zkkzkk commented Nov 4, 2026

Copy link
Copy Markdown

Simplified Chinese (zh-Hans) for both apps, end to end: every string Sill for Mac shows (the status menu and its card, every Settings pane, the pairing window, the update check, the alerts) and the whole iPhone and iPad app (the connect screen, the bars, Settings, the tour, pairing, Remote Access). Related: #237 (a request for Chinese) and #238, a draft that starts the same way for the pairing and connection flows; this one covers the rest too, and I'm happy to coordinate with it or reshape this to whatever you prefer for localization.

How

  • Text that reaches the screen as a plain String (AppKit menu items, alerts, status lines, sentences built in the policies) goes through String(localized:); SwiftUI literals were already localizable and are unchanged. The English is unchanged byte for byte: it is the key, and a missing translation shows it.
  • Sentences assembled from English fragments, and English plurals, became whole sentences, so a language can order them its own way (e.g. wrongCodeLine(from:triesLeft:), the Remote Access note's joiner).
  • Numbers that aren't quantities (ports, pixel sizes, error codes) are interpolated as String(n), so a locale doesn't group them (7,455).
  • Nothing on the wire changes. Strings a Mac sends for a device to show (virtualDisplayNote, the sound's notes) stay English, so mixed versions read each other as before; Sill.log stays English.
  • Sill for Mac: Packaging/Localizable.xcstrings (391 strings) and Packaging/zh-Hans.lproj/InfoPlist.strings (the Local Network prompt); make-app.sh compiles the catalog with xcstringstool compile; Info.plist lists CFBundleLocalizations en and zh-Hans. Scripts/sync-strings.sh re-extracts the Mac's keys after a change (each module exported on its own, since StreamProtocol and SillMenuBar both have a HostSettings.swift).
  • Sill for iPhone and iPad: iOSClient/Localizable.xcstrings (470 strings) and InfoPlist.xcstrings (camera, Local Network); the project gains the zh-Hans region, nothing else in it changes.
  • DEVELOPMENT.md has a new "Translations" section (what is translated, what stays English, adding a language, how to look at one); README's Requirements says both apps are in English and Simplified Chinese.
  • The mutant patterns that named the old literals follow the new source text.

Three commits: the Mac, the iPhone and iPad app, then the script and the docs.

Tested

  • Tests/checks/run-all.sh: all passed, on this branch rebased on main (41e8cb8).
  • Mutants: not run (an hour and more); every mutant pattern of the 14 checks whose files changed is found in the source, none "NOT APPLIED".
  • Scripts/make-app.sh (Sill.app, Apple silicon) and the iOS app for the simulator and a device.
  • Sill for Mac on a MacBook Pro (M5 Pro), macOS 26.7.1, Xcode 27.2, in Chinese and English: the menu, every Settings pane and the pairing window (also through -SillRenderPreviews with -AppleLanguages "(zh-Hans)").
  • Sill for iPhone on an iPhone Duo (a Debug build), looked at in Chinese. Not yet: a full streaming session in Chinese between the two.

The code and the translations were written with AI assistance (Claude Code).

🤖 Generated with Claude Code

zkkzkk and others added 3 commits November 4, 2026 16:31
- Wrap user-visible strings in SillMenuBar, SillHostCore and StreamProtocol with String(localized:), restructuring English-only sentence assembly and plurals into whole sentences
- Add Packaging/Localizable.xcstrings with zh-Hans translations (361 strings) and zh-Hans InfoPlist.strings
- make-app.sh compiles the catalog into the app bundle; Info.plist lists en and zh-Hans
- Interpolate ports, pixel sizes and error codes as text so they don't get grouping separators
- Update mutant patterns in Tests/checks to the wrapped source text

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Wrap the strings iOSClient shows as a plain String with String(localized:); the English text is
  unchanged. Sentences assembled from English fragments become whole sentences chosen by condition.
- The strings in StreamProtocol the device shows (LockedMac, TextScale, ClipboardPolicy.Copy) the
  same way; Packaging/Localizable.xcstrings gains them too, as the Mac compiles that module.
- Add iOSClient/Localizable.xcstrings (470 strings, all with zh-Hans) and InfoPlist.xcstrings (the
  camera and Local Network prompts); the project gains the zh-Hans region.
- The space between a Settings footnote's sentences is localizable (SentenceGap), empty in Chinese.
- Update the mutant patterns the changed lines broke (away-copy, away-wire, clipboard, goodbye,
  home-device, home-model, lock-policy, policy, protocol, thumbnail-hold, tour).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…anguage

- Scripts/sync-strings.sh brings Packaging/Localizable.xcstrings up to date with the Mac's source:
  each module's strings exported on its own (two HostSettings.swift), then xcstringstool sync.
- DEVELOPMENT.md, "Translations": what is translated and what stays English (the wire, Sill.log),
  where each app's catalog is, adding a language, and how to look at one.
- README's Requirements: both apps in English and Simplified Chinese.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Wangnov

Wangnov commented Nov 6, 2026

Copy link
Copy Markdown

Thanks @zkkzkk — #308’s broader native catalog work looks like a good base for Simplified Chinese. My earlier draft #238 covers pairing and connection in both Chinese variants and also includes some state-handling fixes.

I’ve extracted those fixes into #317 (six iOS files, no catalogs or build changes); it applies cleanly to your current head, 2533106. I’m keeping #238 as a draft to avoid competing catalog changes. Its Traditional Chinese translations can be adapted to these catalogs after this lands — the existing translations cover only part of your expanded UI, so that will need a separate pass.

This keeps the state fixes independently reviewable and avoids duplicating your Simplified Chinese work.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants