feat(translation-ui): tighten settings/onboarding UX around the translation feature
UI refinements on top of the translation pipeline (feature/translation@HEAD):
1. Onboarding engine page now hosts a translation row.
APISetupPage renders the same TranslationPickerRow used in the
language tab, so first-time users can pick a target language
before they ever see the keyboard. Same persisted bindings; same
'needs cloud' hint when the local engine is active.
2. Local engine hides the provider / API card unconditionally.
Removed the 'local + cloud polish on → show API fields' branch
from SettingsView. Provider/base URL/API key/model controls have
no use in local mode (translation is cloud-only anyway), and
exposing them invited users to fill in a DeepSeek key they
can't use.
3. 'Cloud polish after ASR' toggle loses its long subtitle.
The descriptive copy in LocalEngineSettingsRows.cloudPolishRow
was a wall of text that explained things visible elsewhere in
Settings. Title + switch is enough; the CloudPolishDisclosureBanner
(rendered by EnginePickerSection when cloud is active) already
covers the 'this sends text to your API' disclosure.
4. Translation row becomes a single dropdown with a 'Don't
translate' default.
TranslationPickerRow replaced with a one-row Menu picker:
'不翻译 / English / 中文 (简体) / 中文 (繁體) / 日本語 / 한국어 /
Français / Deutsch / Español / Русский / Português'.
'不翻译' maps to translationEnabled=false; any locale maps to
translationEnabled=true + translationTargetLocaleId=<id>.
TranslationLanguageCatalog gains an 'off' sentinel so the picker's
single binding stays a plain String.
5. Language tab reorder.
SettingsView.languageAndModelsSection: ASR locale ('识别语言')
now sits above the local-models block; translation row sits at
the bottom. The reading order follows the pipeline direction
(input → post-processing → post-post-processing).
Localization:
- 'settings.translation.title' → '翻译' / 'Translation'
- new 'settings.translation.off' / 'settings.translation.hint.needsCloud'
- dropped unused subtitle / target-language keys
xcodebuild scheme=OSGKeyboard config=Debug destination=iPhone 17
Simulator: BUILD SUCCEEDED (0 warning, 0 error).
This commit is contained in:
@@ -62,17 +62,16 @@ struct SettingsView: View {
|
||||
VStack(spacing: Spacing.md) {
|
||||
appLanguageSection
|
||||
engineSection
|
||||
// v0.2.1: hide provider/api card when the
|
||||
// local engine is active regardless of the
|
||||
// cloud-polish toggle. Local mode is
|
||||
// contractually ASR-only, so provider/model/
|
||||
// base URL/API key controls have no use —
|
||||
// and exposing them invites the user to fill
|
||||
// out a DeepSeek key they can't use.
|
||||
if config.engineMode == "cloud" {
|
||||
providerSection
|
||||
apiSection
|
||||
} else if config.localModeCloudPolishEnabled {
|
||||
// v0.2.0: local engine + cloud polish on.
|
||||
// Surface the provider / API key fields so
|
||||
// the user can fill in their DeepSeek key.
|
||||
// We hide them when the toggle is off so the
|
||||
// local engine stays genuinely local.
|
||||
providerSection
|
||||
apiSection
|
||||
}
|
||||
languageAndModelsSection
|
||||
if config.engineMode == "cloud" {
|
||||
@@ -128,10 +127,12 @@ struct SettingsView: View {
|
||||
VStack(alignment: .leading, spacing: SettingsListMetrics.sectionLabelSpacing) {
|
||||
sectionHeader("settings.language.title")
|
||||
VStack(spacing: 0) {
|
||||
if config.engineMode == "local" {
|
||||
LocalModelsGroup(config: config)
|
||||
Divider().background(palette.divider)
|
||||
}
|
||||
// v0.2.1: language tab reorder — ASR locale ("识别语言")
|
||||
// now sits above the cloud-polish toggle / local models
|
||||
// block so the row that maps to microphone input comes
|
||||
// first, the row that maps to post-processing comes
|
||||
// second, and translation (post-post-processing) sits at
|
||||
// the bottom.
|
||||
LocalePickerRow(
|
||||
locales: effectiveLocales,
|
||||
selection: Binding(
|
||||
@@ -139,11 +140,10 @@ struct SettingsView: View {
|
||||
set: { config.localeId = $0 }
|
||||
)
|
||||
)
|
||||
// v0.2.1: translation toggle + target-language picker.
|
||||
// Sits at the bottom of the language section so the user
|
||||
// finds it next to the ASR locale it complements. Reuses
|
||||
// `config.translationEnabled` / `config.translationTargetLocaleId`
|
||||
// bindings — no new state, no new persistence path.
|
||||
if config.engineMode == "local" {
|
||||
Divider().background(palette.divider)
|
||||
LocalModelsGroup(config: config)
|
||||
}
|
||||
Divider().background(palette.divider)
|
||||
TranslationPickerRow(config: config)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user