---
title: william-weng/wwtranslationmanager
framework: Swift Package Catalog
role: article
path: packages/william-weng/wwtranslationmanager
---

# william-weng/wwtranslationmanager

[English](./README.en.md) | [正體中文](./README.md)

## ✨ 特色

- 專為 UIKit 專案設計，無須將整個畫面改寫成 SwiftUI。 - 使用 Apple Translation 框架提供端側（On-device）翻譯。 - 支援系統原生語言包下載與授權對話框。 - 以隱藏的 `UIHostingController` 作為 UIKit 與 SwiftUI 之間的橋樑。 - 可透過 `TranslationSession.Configuration` 自訂翻譯設定。 - 支援重複翻譯請求，並會自動更新或使既有設定失效。 - API 受到 `@MainActor` 保護，適合在 UIKit 主執行緒中使用。 - 管理器解除初始化時，會自動移除內部的 Hosting Controller。

> ⚠️ Apple Translation 的實際可用性會受到裝置系統版本、來源語言、目標語言、語言包狀態與裝置支援情況影響。

## 📦 安裝方式

### Swift Package Manager

```bash swift package add https://github.com/William-Weng/WWTranslationManager.git ```

或在 Xcode 中：

``` File → Add Packages → https://github.com/William-Weng/WWTranslationManager.git ```

## 📌 公開屬性

| 名稱 | 型別 | 適用 | 說明 | | --- | --- | --- | --- | | `configuration` | `TranslationSession.Configuration` | `全部` | 翻譯配置設定。預設為 `.init()`，會依系統環境自動判斷翻譯語言。 |

## 🏗️ 公開 API

| API | 宣告 | 適用 | 說明 | | --- | --- | --- | --- | | `init(attachingTo:)` | `init(attachingTo viewController: UIViewController)` | `全部` | 初始化翻譯管理器，並將隱藏的 SwiftUI Hosting Controller 掛載至指定的 `UIViewController`。 | | `translate(_:completion:failure:)` | `func translate(_ text: String, completion: @escaping (_ translatedText: String) -> Void, failure: @escaping (Error) -> Void)` | `WWTranslationManager` | 透過 completion handler 非同步執行文字翻譯。 | | `translate(batch:completion:failure:)` | `func translate(batch texts: [String], completion: @escaping (WWTranslationBatchResult) -> Void, failure: @escaping (Error) -> Void)` | `WWTranslationBatchManager` | 批次翻譯多個字串（使用串流模式）。 | | `translate(from:completion:failure:)` | `func translate(from texts: [String], completion: @escaping ([WWTranslationBatchResult]) -> Void, failure: @escaping (Error) -> Void)` | `WWTranslationBatchCoordinatorManager` | 批次翻譯多個字串（一次回傳）。 | | `translate(_:)` | `func translate(_ text: String) async throws -> String` | `WWTranslationManager` | 透過 Swift Concurrency 非同步執行文字翻譯。翻譯失敗時會拋出錯誤。 | | `translate(batch:)` | `func translate(batch texts: [String]) async throws -> AsyncThrowingStream<WWTranslationBatchResult, Error>` | `WWTranslationBatchManager` | 批次翻譯多個字串（使用串流模式）。 | | `translate(from:)` | `func translate(from texts: [String]) async throws -> [WWTranslationBatchResult]` | `WWTranslationBatchCoordinatorManager` | 批次翻譯多個字串（一次回傳）。 |

## 🧠 運作方式

`WWTranslationManager` 會在初始化時建立一個隱藏的 `UIHostingController`，並將它加入指定的 UIKit View Controller 階層中。

翻譯流程如下：

1. 將待翻譯文字與成功、失敗回呼交給內部 Bridge。 2. 將公開的 `TranslationSession.Configuration` 同步至 SwiftUI Bridge View。 3. 由 Apple Translation 顯示必要的語言包下載或使用者授權介面。 4. 使用端側翻譯功能處理文字。 5. 透過 `completion` 或 `failure` 回傳結果。 6. 管理器釋放時移除隱藏的 Hosting Controller。

> 這種設計可以將 SwiftUI `translationTask` 相關邏輯集中在內部，而 UIKit 呼叫端只需要處理簡單的文字輸入與結果回呼。

## ⚠️ 注意事項

- 請在主執行緒建立與使用 `WWTranslationManager`，因為此類別標記為 `@MainActor`。 - 管理器應該由畫面或對應的 Coordinator 持有，避免剛建立後便被釋放。 - `attachingTo` 傳入的 View Controller 必須已經具有有效的 View 階層。 - 首次翻譯特定語言組合時，系統可能要求下載語言包。 - 端側翻譯不代表所有語言組合都能離線使用，實際結果取決於裝置上的語言包。 - 如果連續送出多個翻譯請求，建議在上一個請求完成後再開始下一個請求，以避免回呼結果互相覆蓋。 - 發生錯誤時，請在 `failure` 閉包中處理 UI 狀態，例如顯示提示、保留原文或提供重試按鈕。

## 🧪 完整範例

```swift import UIKit import WWTranslationManager

final class ViewController: UIViewController {          @IBOutlet weak var sourceLabel: UILabel!     @IBOutlet weak var targetLabel: UILabel!          private var manager: WWTranslationManager?          override func viewDidLoad() {         super.viewDidLoad()         manager = .init(attachingTo: self)     }          @IBAction func translateAction(_ sender: UIButton) {                  guard let source = sourceLabel.text else { return }                  manager?.translate(source, completion: { [weak self] translatedText in             self?.targetLabel.text = translatedText         }, failure: { error in             print("翻譯失敗或使用者取消下載: \(error.localizedDescription)")         })     }          @IBAction func translateEnglish(_ sender: UIButton) {         sourceLabel.text = "Offer in-app translations with the Translation framework. You can use the built-in UI and let the system offer a translation to users on your behalf. Or you can use the framework to customize the translation experience."         targetLabel.text = "<Loading...>"     }          @IBAction func translateJapanese(_ sender: UIButton) {                  manager?.configuration = .init(source: .init(identifier: "ja-JP"), target: .init(identifier: "en-US"))                  sourceLabel.text = "「映画ちいかわ 人魚の島のひみつ」"         targetLabel.text = "<Loading...>"     } } ```

## Package Metadata

Repository: william-weng/wwtranslationmanager

Default branch: main

README: README.md
