| title | Localization |
|---|---|
| description | How to report, repair, test, and contribute Rockxy translations or add a new language |
Rockxy uses native Xcode String Catalogs (.xcstrings). The catalogs checked
into the repository are the single source of truth for every translation. There is
an app-language picker under Settings › Appearance › Language. System Default
follows the macOS language; choosing another bundled language updates the running
Rockxy UI immediately without stopping capture or reopening the app.
The picker reads the localizations available in the application bundle instead of hardcoding a language list, so a newly contributed and shipped catalog appears there automatically.
| Catalog | Covers |
|---|---|
Rockxy/Localizable.xcstrings |
All in-app UI strings |
Rockxy/InfoPlist.xcstrings |
Info.plist user-facing text (e.g. the Local Network usage prompt) |
The source language is English (en). The first shipped translation is
Simplified Chinese (zh-Hans). knownRegions in
Rockxy.xcodeproj/project.pbxproj lists every language the project builds.
Rockxy accepts localization contributions for every language, including:
- inaccurate, unnatural, overly literal, or culturally inappropriate wording,
- text that is too long, clipped, or unclear in its actual UI context,
- incorrect technical terminology or inconsistent wording,
- missing translator context and corrections to the English source,
- complete translations for a new language.
You do not need to be a programmer or have Xcode to report or repair a small translation. If you prefer not to edit a catalog, open a Translation Improvement issue with the language, where the text appears, the current wording, your proposed wording, and why it is better.
Use compile-time-extractable APIs so Xcode can find every string automatically:
Text("Start Proxy") // SwiftUI literals auto-localize
String(localized: "Request Body Options") // explicit localization
LocalizedStringResource("Make Rockxy reachable from the device")Rules that keep extraction clean and translations safe:
-
No dynamic keys. Never build a key from a runtime value (
String(localized: String.LocalizationValue(name)),"\(count) item\(count == 1 ? "" : "s")"). The compiler cannot extract these and translators never see them. Pass aLocalizedStringResourceliteral into helpers instead of aString. -
Pluralization uses Apple's automatic grammar agreement, not a hand-rolled
"s"suffix:String(localized: "^[\(count) request](inflect: true)")
For languages such as Chinese that have no plural inflection, the translated string is used verbatim — which is exactly why the ternary approach was unsafe.
-
Never translate identifiers. URLs, routes, MIME types, header names (
Content-Type), format tokens, code fragments, keyboard notation (⌘K), file extensions, and product/protocol names stay verbatim. If a whole string is an identifier, mark the catalog entry Don't Translate ("shouldTranslate": false), or keep it out of a localized API. -
Comments are for translators. Add a
commentto any catalog entry whose meaning is ambiguous out of context, and to flag tokens that must stay verbatim.
- Translate meaning in context. Prefer natural product language in the target language over word-for-word English structure.
- Preserve technical meaning. A polished sentence that changes how a proxy, certificate, rule, or destructive action behaves is not an acceptable translation.
- Keep the UI concise. Match the tone of a native macOS application and check that labels, buttons, menus, tables, and settings do not truncate.
- Be consistent. Reuse established translations for the same action or concept.
- Review generated drafts. Machine translation may be used as a starting point, but do not submit bulk-generated catalog output without fluent human review.
- Protect user data. Redact private URLs, headers, credentials, tokens, request bodies, and captured traffic from screenshots or examples.
Translation repair PRs are welcome, including PRs that change only one phrase. A small, focused correction is easier to review and does not need unrelated catalog entries, Swift tests, SwiftLint, SwiftFormat, or a changelog entry.
For a small repair, GitHub's web editor or any UTF-8 text editor is enough:
- Fork the repository and create a branch from
develop. - Search
Rockxy/Localizable.xcstringsorRockxy/InfoPlist.xcstringsfor the exact text currently shown in the app. - In that entry's
localizationsobject, change only thevaluefor your locale. Do not rename the English key, reorder the whole file, or reformat unrelated JSON. - Run
python3 .github/tools/validate_xcstrings.py --no-compile. This needs only Python 3 and works without Xcode on macOS, Linux, and Windows (where the command may bepythoninstead ofpython3). - Open a PR against
developand complete the localization section of the PR template.
- Open
Rockxy.xcodeprojand select the affected.xcstringscatalog. - Filter by the target language or search for the English key/current translation.
- Edit only the affected localized value and review every variation shown by Xcode.
- Run the validator and verify the changed UI in Rockxy.
- Open a focused PR against
develop.
For either workflow, include the locale, affected screen or catalog key, and a short reason the wording is better. Useful evidence can be native-speaker knowledge, a platform terminology reference, a screenshot showing context or truncation, or a clear explanation of the technical meaning. A public citation is helpful when one exists, but it is not required for ordinary native-language corrections.
If the English source is wrong, say so explicitly. Changing an English key can affect every locale, so update the impacted translations or keep the source change in a separate PR that can receive broader review.
Anyone may contribute a language through a normal reviewed pull request:
- Choose the standard locale identifier used by Apple, such as
de,fr,ja,ko,zh-Hant, orpt-BR. Use a region-specific locale only when the wording genuinely differs from the base language. - Open
Rockxy/Localizable.xcstringsandRockxy/InfoPlist.xcstringsin Xcode. - Add the same language to both catalogs from the catalog's + control.
Confirm Xcode also added the locale to
knownRegionsinRockxy.xcodeproj/project.pbxproj. - Translate every translatable entry. Preserve, exactly:
- placeholders and their order (
%@,%lld, positional%1$@/%2$lld), - plural / device variations,
- leading/trailing whitespace and newlines,
- Markdown and HTML fragments,
- keyboard notation, file extensions, and technical/product terms.
- placeholders and their order (
- Run
python3 .github/tools/validate_xcstrings.py --require <locale>until it is clean. The default validator also discovers and checks every locale present in either catalog. - Build Rockxy, select the new language under Settings › Appearance › Language, and inspect the important surfaces listed below.
- Open a PR against
develop. A maintainer reviews every.xcstringschange (see.github/CODEOWNERS) — this protects placeholder integrity and the shared English source, and does not block your contribution.
Translations may land as a first pass and be refined later, but a language should not be advertised as supported until its runtime coverage is complete — every translatable entry has a non-empty value.
Unless the term has an established localized product spelling, preserve these exactly:
- placeholders and their order (
%@,%lld,%1$@,%2$lld), - protocol and product names (
HTTP,HTTPS,WebSocket,GraphQL,MCP,Rockxy), - header names, MIME types, URLs, routes, file extensions, and code fragments,
- keyboard notation and shortcuts,
- Markdown/HTML structure, intentional whitespace, and newlines.
If a technical token must move to make the sentence natural, use positional placeholders so its semantic argument order remains unambiguous; do not change the placeholder's conversion type.
Catalog validation proves structure and placeholder safety, but it cannot judge language quality or layout. Before marking a new-language PR ready, select the language in Rockxy and review at least:
- onboarding and permission dialogs,
- Settings, including Appearance › Language,
- the main capture toolbar, traffic list, filters, and empty states,
- request/response inspectors and error messages,
- rules, breakpoints, certificate, import/export, and destructive confirmations,
- menus, tooltips, keyboard shortcuts, and
Info.plistpermission prompts.
Look for clipping, overlapping controls, untranslated English, incorrect plural or format substitutions, and wording that changes the action's meaning. Attach focused, redacted screenshots to the PR when a reviewer cannot infer the UI context from the catalog key alone.
Run the deterministic validator before pushing. It needs no secrets or third-party packages, so it runs the same way locally and in CI:
# Validate both catalogs and every locale discovered in either catalog
python3 .github/tools/validate_xcstrings.py
# Require a specific language (or several) explicitly
python3 .github/tools/validate_xcstrings.py --require zh-Hans,de
# Skip the optional xcstringstool compile (e.g. on a non-macOS machine)
python3 .github/tools/validate_xcstrings.py --no-compileThe validator checks: valid JSON, sourceLanguage == en, matching locale coverage
across both catalogs, full coverage for every discovered or explicitly required
language, parity with the Xcode project's knownRegions, no empty values, variation
parity, and placeholder parity between the source and every translation. When
Xcode's toolchain is available it also compiles each catalog with
xcrun xcstringstool compile. You can compile a catalog by hand too:
xcrun xcstringstool compile --output-directory /tmp/xcstrings Rockxy/Localizable.xcstringsCI runs this validator on every pull request in the Localization Catalogs job.
Because the check carries no secrets and no write access, it runs safely on fork
PRs without exposing them to privileged jobs.
If the project ever adopts an external translation platform, it is only a mirror.
The Git-tracked .xcstrings catalogs remain canonical. Any platform integration must
land translations the same way a human does — by opening a reviewed pull request that
edits the catalogs — and must never push directly to the repository or bypass the
maintainer review gate. Configure such tooling through the project owner; do not add
platform credentials or account details to the repository.