feat(translation): add post-ASR translation mode for cloud engine
Adds an opt-in translation pipeline that reuses the existing PolishingService + LLMClient + AppGroupStore chain. Translation is implemented as a new PolishMode (.translate(targetLocaleId:)); all existing call sites are unchanged. Settings: - New TranslationPickerRow in the language tab (Toggle + 10-locale picker: en/zh-Hans/zh-Hant/ja/ko/fr/de/es/ru/pt), persisted to the App Group so the keyboard extension can read it during live dictation. - 5 new strings per language (en + zh-Hans). Keyboard: - New TranslationChip on the top bar to the right of LocaleChip; same Menu pattern, lets users toggle or quickly switch target language without leaving the keyboard. - PolishingService dispatches .translate with a parameterised prompt (en/zh variants selected by provider id); PolishingService.error gains a translationNotAvailable case so local-engine users get a clear inline warning when the toggle is on but cloud is off. - 6 new strings per language (en + zh-Hans) for the chip + banner. Local engine policy: - Translation is cloud-only by design (local engine stays ASR-only to honour the no-roundtrip promise). Chip shows a 'cloud required' state and raw transcript still inserts on failure — no data loss. Build: - OSGKeyboardShared adds TranslationLanguage enum (10 locales) and TranslationPrompt factory. - 4 new files, 9 modified. xcodebuild scheme=OSGKeyboard config=Debug destination=iPhone 17 Simulator: BUILD SUCCEEDED (0 warning, 0 error). Also pins DEVELOPMENT_TEAM in project.yml for TestFlight uploads (3 targets; Team X329MZU23S).
This commit is contained in:
@@ -87,6 +87,20 @@ public final class KeyboardState: ObservableObject {
|
||||
/// CoreML local engine. Always `false` now — there are no weights
|
||||
/// for the host app to preload.
|
||||
@Published public var localModelsLoaded: Bool = false
|
||||
/// v0.2.1: translation toggle mirrored from `ProviderConfig`. The
|
||||
/// pipeline asks `isTranslationEffective` before honouring it —
|
||||
/// the local engine ignores translation regardless of this flag.
|
||||
@Published public var translationEnabled: Bool = false
|
||||
/// v0.2.1: target locale id the translate-and-polish prompt should
|
||||
/// produce (e.g. `"en"`, `"ja"`). Mirrored from `ProviderConfig`.
|
||||
@Published public var translationTargetLocaleId: String = TranslationLanguageCatalog.defaultLocaleId
|
||||
/// v0.2.1: effective predicate — translation is honoured only on
|
||||
/// the cloud engine. The keyboard's chip / picker read this so the
|
||||
/// UI can show a "需要云端" hint when the toggle is on while the
|
||||
/// local engine is active.
|
||||
public var isTranslationEffective: Bool {
|
||||
translationEnabled && engineMode == "cloud"
|
||||
}
|
||||
|
||||
/// Convenience shorthand used by the pipeline and views.
|
||||
public var isLocalEngine: Bool { engineMode == "local" }
|
||||
@@ -101,6 +115,12 @@ public final class KeyboardState: ObservableObject {
|
||||
public var setLocale: (String) -> Void = { _ in }
|
||||
public var setEngineMode: (String) -> Void = { _ in }
|
||||
public var setLocalASRBackend: (LocalASRBackend) -> Void = { _ in }
|
||||
/// v0.2.1: persist translation toggle. Wired in
|
||||
/// `KeyboardViewController.installStateActions`.
|
||||
public var setTranslationEnabled: (Bool) -> Void = { _ in }
|
||||
/// v0.2.1: persist translation target locale id. Same wiring as
|
||||
/// `setTranslationEnabled`.
|
||||
public var setTranslationTargetLocaleId: (String) -> Void = { _ in }
|
||||
public var insertNewline: () -> Void = {}
|
||||
public var insertSpace: () -> Void = {}
|
||||
public var deleteBackward: () -> Void = {}
|
||||
|
||||
Reference in New Issue
Block a user