Pre-Babel Lenz is a local translation application using Apple's In Device Foundation Models. Translation using LLM is possible even in places without an internet connection. Additionally, since the translated text is not sent to an external server, it can be used safely when dealing with privacy or confidential information.
- Please enable Apple Intelligence.
If you set up the Automator workflow as described in the README, you can translate text selected in Mac applications. You can also translate from shortcuts set in the workflow.
Repository: https://github.com/ttrace/pre-babel-lens
You can launch translation quickly with a DeepL-like flow:
- Select text in any app.
- Press
Command + Ctwice quickly (Cmd+C,Cmd+Cwithin about 1 second). - Pre-Babel Lens comes to front and starts translation with the selected text.
Notes:
- This feature watches clipboard changes on macOS only.
- It ignores empty text and applies the same duplicate suppression logic used by URL launch.
You can launch translation from selected text via Automator.
- Open Automator and create a new
Quick Action. - Set:
Workflow receives current:textin:any application
- Add
Run Shell Script. - Set:
Shell:/bin/zshPass input:to stdin
- Paste this script:
#!/bin/zsh
text="$(cat)"
if [ -z "$text" ]; then
text="$*"
fi
if [ -z "$text" ]; then
exit 0
fi
encoded="$(printf '%s' "$text" | /usr/bin/python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read()))')"
open "prebabellens://translate?text=${encoded}"- Save (for example:
Translate with Pre-Babel Lens). - Assign a keyboard shortcut from
System Settings > Keyboard > Keyboard Shortcuts > Services.
Notes:
- The app keeps your current target language and updates the existing window content.
- If Automator sends the same
text + target languageagain, duplicate translation is skipped.
If Apple Intelligence blocks a segment as unsafe, Pre-Babel Lens stops retrying that segment and shows a clear fallback instead.
Current behavior:
- The blocked segment falls back to the original source text.
- Unsafe-source fallback is shown as original text with a distinct text color and marker-style background.
- Other segments can continue translating when possible.
When a segment cannot be translated cleanly, the Foundation Models engine applies the following recovery flow:
- Normal segment translation:
- Each segment is translated with structured output (
targetLanguage,translation).
- Each segment is translated with structured output (
- Context window overflow:
- If an error contains
Exceeded model context window size, the engine recreatesLanguageModelSessionand retries that segment once. - If retry succeeds, translation continues.
- If retry fails, the segment falls back to source text.
- If an error contains
- Sentence-drop safeguard:
- After translation, sentence counts are compared (
inputvsoutput). - If
output < input/2, the segment is retried once with a fresh session. - Exception:
2 -> 1is explicitly allowed. - If retry fails, the first translation result is kept.
- Unsafe-content failures skip this retry path and return source text immediately.
- After translation, sentence counts are compared (
- Structured-output mismatch:
- If structured output validation fails (for example target language mismatch / empty / placeholder), the segment falls back to source text.
- Unsafe content:
- If Foundation Models reports a safety or policy restriction, the segment falls back to source text with a distinct text color and marker-style background.
- This path is treated as no-retry to avoid repeated blocked generations.
- Cancellation handling:
- Cancellation is propagated immediately (not converted to source fallback), so stopped jobs can drain cleanly.
Developer Console diagnostics include:
context-window-exceeded-refresh-session-and-retryresumed-after-session-refreshretry-after-session-refresh-failed-source-returnedsentence-count-drop-detected retry-oncesentence-count-retry-finishedsentence-count-retry-failed-keep-firststructured-output-no-retry-source-returnedunsafe-no-retry-source-returned
Sources/App/: app entry pointSources/Features/Translation/: translation UI and view modelSources/Domain/: core models and protocolsSources/Engines/Preprocess/: deterministic preprocessingSources/Engines/Translation/: translation engine stubsSources/Services/: orchestration and engine policyTests/: unit tests
swift buildswift testThis project's official release artifacts are built locally, signed locally, and notarized locally. Do not use GitHub-hosted CI build artifacts as official distributables.
Preferred release script:
scripts/build_notarized_release.shCredential options:
- Recommended:
NOTARY_PROFILE(Keychain profile created byxcrun notarytool store-credentials) - Legacy fallback:
APPLE_ID+ app-specific password +APPLE_TEAM_ID
The script performs:
- local release build
- Developer ID code signing
- notarization submission/wait
- stapling and validation
When a segment cannot be translated cleanly, the Foundation Models engine applies the following recovery flow:
- Normal segment translation:
- Each segment is translated with structured output (
targetLanguage,translation).
- Each segment is translated with structured output (
- Context window overflow:
- If an error contains
Exceeded model context window size, the engine recreatesLanguageModelSessionand retries that segment once. - If retry succeeds, translation continues.
- If retry fails, the segment falls back to source text.
- If an error contains
- Sentence-drop safeguard:
- After translation, sentence counts are compared (
inputvsoutput). - If
output < input/2, the segment is retried once with a fresh session. - Exception:
2 -> 1is explicitly allowed. - If retry fails, the first translation result is kept.
- After translation, sentence counts are compared (
- Structured-output mismatch:
- If structured output validation fails (for example target language mismatch / empty / placeholder), the segment falls back to source text.
- Cancellation handling:
- Cancellation is propagated immediately (not converted to source fallback), so stopped jobs can drain cleanly.
Developer Console diagnostics include:
context-window-exceeded-refresh-session-and-retryresumed-after-session-refreshretry-after-session-refresh-failed-source-returnedsentence-count-drop-detected retry-oncesentence-count-retry-finishedsentence-count-retry-failed-keep-firststructured-output-no-retry-source-returned
This project is licensed under the MIT License. See LICENSE.
