TL;DR
A developer tried to build a tiny command-line translator using macOS's Translation service instead of third-party APIs. The effort revealed tooling quirks, async interop traps, and sparse documentation for using the Translation API outside SwiftUI.
What happened
The author wanted a simple terminal command to translate short Chinese text and first considered third-party translation APIs but found them to require API keys, rate limits and possible billing. They then tried to reuse macOS's built-in Translate capability. An initial attempt in Zig failed because the example used the Dictionary service and calling Swift async APIs from Zig proved impractical. Switching to Swift, the author iterated on a command-line tool, adjusting Package.swift and removing example dependencies. They ran into multiple friction points: passing arguments with swift run, the TranslationSession initializer requiring a known source language and being restricted to macOS 26, and the need to make the command async. Early attempts used Task plus a DispatchSemaphore as a workaround; switching from ParsableCommand to AsyncParsableCommand fixed the async entry point. Even then the translation call sometimes returned an "Unable to Translate" error and language autodetection remained hardcoded, while most examples and docs were focused on SwiftUI and not CLI use.
Why it matters
- System APIs can be hard to use for small developer tools when documentation centers on a different platform (SwiftUI) than the intended usage (CLI).
- Async APIs introduce new control-flow and entry-point requirements that can surprise developers moving between languages and runtimes.
- Tooling and manifest metadata (swift-tools-version, platform constants) affect compatibility in non-obvious ways and can block compilation or selection of APIs.
- Sparse or unhelpful runtime errors make debugging integration issues significantly harder for developers building small utilities.
Key facts
- The author wanted a command-line translator to convert input like “translate 你好” to “Hello”.
- They initially looked at third-party translation APIs but noted those often require API tokens, rate limits, and possibly credit cards.
- An early implementation attempt in Zig used the Dictionary service rather than the Translation service and hit interop limits with Swift async functions.
- Switching to Swift, the author adapted a small ParsableCommand-based CLI example and removed example Figlet dependency.
- TranslationSession.init requires a known source language and is restricted to macOS 26 according to the author’s tests.
- Changing the swift-tools-version declaration in Package.swift allowed the author to target the newer macOS platform constant (.v26).
- Using Task with a DispatchSemaphore briefly worked as a sync workaround before adopting AsyncParsableCommand to support an async run method.
- After switching to AsyncParsableCommand and awaiting session.translate, the tool still sometimes returned an "Unable to Translate" error and the code used a hardcoded source language rather than autodetection.
- Most available examples and documentation the author found were SwiftUI-focused and did not cover non-SwiftUI CLI usage of the Translation API.
What to watch next
- Documentation or example updates that demonstrate using the Translation API outside SwiftUI (e.g., in CLI tools).
- Improvements in TranslationSession error reporting and clearer guidance on language autodetection for non-UI use cases.
- not confirmed in the source
Quick glossary
- TranslationSession: An API object used to perform translation operations within Apple's Translation framework.
- Async/await: Language constructs for writing asynchronous code in a sequential style; awaiting suspends until an asynchronous operation completes.
- Package.swift: The Swift Package Manager manifest file that describes a package’s name, dependencies, targets, and platform requirements.
- Swift Argument Parser: A Swift package that helps build command-line tools by defining commands, options, and arguments.
- DispatchSemaphore: A low-level concurrency primitive used to coordinate threads or tasks by blocking until a signal is received.
Reader FAQ
Why didn’t the author just use an online translation API?
The author noted many third-party APIs required API tokens, had rate limits and sometimes required billing details.
Why did the Zig attempt fail?
The Zig example called the Dictionary service instead of the Translation service, and the author encountered issues calling Swift async functions from Zig.
How was the async entry-point problem resolved?
Replacing ParsableCommand with AsyncParsableCommand allowed defining an async run() that could await translation calls.
Did the translation CLI ultimately work reliably?
The author reports getting an "Unable to Translate" error in some runs and relied on a hardcoded source language; broader success was not established.
In the ongoing effort for activities that fill the void made by unemployment, I have recently started to learn Chinese. Got into a Chinese language institute and everything. And because…
Sources
- The unbearable frustration of figuring out APIs
- The Unbearable Frustration of Figuring Out APIs
- LIVES NOT LIVED Monika Bhatti – Googleapis.com
- Transform Your Life with Holistic Lipedema Approach
Related posts
- Scaling Autonomous Coding: Running Hundreds of Agents for Weeks
- Xoscript: a minimalist server-side scripting language revived in 2026
- Webctl: CLI browser automation for AI agents as alternative to MCP