Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 135 additions & 30 deletions Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -7048,177 +7048,282 @@
}
}
},
"Ready using another installed translation mode.": {
"Source language to check": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Ready using another installed translation mode."
"value": "Source language to check"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "설치된 다른 번역 방식으로 번역할 수 있어요."
"value": "준비 상태를 확인할 원문 언어"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "インストール済みの別の翻訳方式で翻訳できます。"
"value": "準備状況を確認する原文の言語"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "可使用另一种已安装的翻译模式进行翻译。"
"value": "要检查准备状态的源语言"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "可使用另一種已安裝的翻譯模式進行翻譯。"
"value": "要檢查準備狀態的來源語言"
}
}
}
},
"Source language to check": {
"This checks only this language pair. Your source-language setting stays unchanged.": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Source language to check"
"value": "This checks only this language pair. Your source-language setting stays unchanged."
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "준비 상태를 확인할 원문 언어"
"value": "선택한 두 언어의 준비 상태만 확인해요. 앱의 원문 언어 설정은 바뀌지 않아요."
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "準備状況を確認する原文の言語"
"value": "選んだ言語の組み合わせだけを確認します。アプリの原文言語の設定は変わりません。"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "要检查准备状态的源语言"
"value": "仅检查所选语言组合,应用的源语言设置不会更改。"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "要檢查準備狀態的來源語言"
"value": "僅檢查所選語言組合,App 的來源語言設定不會變更。"
}
}
}
},
"This checks only this language pair. Your source-language setting stays unchanged.": {
"This language pair is not supported. Choose another language.": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "This checks only this language pair. Your source-language setting stays unchanged."
"value": "This language pair is not supported. Choose another language."
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "선택한 두 언어의 준비 상태만 확인해요. 앱의 원문 언어 설정은 바뀌지 않아요."
"value": "지원하지 않는 언어 조합이에요. 다른 언어를 선택해 주세요."
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "選んだ言語の組み合わせだけを確認します。アプリの原文言語の設定は変わりません。"
"value": "この言語の組み合わせには対応していません。別の言語を選んでください。"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "仅检查所选语言组合,应用的源语言设置不会更改。"
"value": "不支持此语言组合,请选择其他语言。"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "僅檢查所選語言組合,App 的來源語言設定不會變更。"
"value": "不支援此語言組合,請選擇其他語言。"
}
}
}
},
"This language pair is not supported. Choose another language.": {
"Translations that follow the page": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "This language pair is not supported. Choose another language."
"value": "Translations that follow the page"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "지원하지 않는 언어 조합이에요. 다른 언어를 선택해 주세요."
"value": "원문의 흐름을 살리는 번역"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "この言語の組み合わせには対応していません。別の言語を選んでください。"
"value": "原文の流れに沿った翻訳"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "不支持此语言组合,请选择其他语言。"
"value": "保留原文结构的翻译"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "不支援此語言組合,請選擇其他語言。"
"value": "保留原文結構的翻譯"
}
}
}
},
"Translations that follow the page": {
"Download languages for the selected translation mode.": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Translations that follow the page"
"value": "Download languages for the selected translation mode."
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "원문의 흐름을 살리는 번역"
"value": "선택한 번역 방식의 언어를 다운로드해 주세요."
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "原文の流れに沿った翻訳"
"value": "選択した翻訳方式の言語をダウンロードしてください。"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "保留原文结构的翻译"
"value": "请下载所选翻译模式的语言。"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "保留原文結構的翻譯"
"value": "請下載所選翻譯模式的語言。"
}
}
}
},
"You can translate now using another installed mode.": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "You can translate now using another installed mode."
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "지금은 설치된 다른 방식으로 번역할 수 있어요."
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "今はインストール済みの別の方式で翻訳できます。"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "目前可使用另一种已安装的模式进行翻译。"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "目前可使用另一種已安裝的模式進行翻譯。"
}
}
}
},
"The selected translation mode does not support this language pair.": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "The selected translation mode does not support this language pair."
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "선택한 번역 방식은 이 언어 조합을 지원하지 않아요."
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "選択した翻訳方式はこの言語の組み合わせに対応していません。"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "所选翻译模式不支持此语言组合。"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "所選翻譯模式不支援此語言組合。"
}
}
}
},
"Download the languages to use another translation mode.": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Download the languages to use another translation mode."
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "다른 번역 방식을 사용하려면 언어를 다운로드해 주세요."
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "別の翻訳方式を使うには、言語をダウンロードしてください。"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "请下载语言以使用另一种翻译模式。"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "請下載語言以使用另一種翻譯模式。"
}
}
}
Expand Down
31 changes: 29 additions & 2 deletions Sources/Dependencies/LanguageCatalogClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ extension LanguageCatalogClient: DependencyKey {
let alternative: TranslationStrategy = strategy == .lowLatency ? .highFidelity : .lowLatency
let other = await LanguageAvailability(preferredStrategy: alternative.sessionStrategy)
.status(from: source.localeLanguage, to: target.localeLanguage)
if other == .installed { return .alternativeInstalled }
return status == .unsupported && other == .unsupported ? .unsupported : .downloadRequired
return LanguageReadiness.resolve(preferred: status, alternative: other)
}
let status = await LanguageAvailability().status(from: source.localeLanguage, to: target.localeLanguage)
switch status {
Expand Down Expand Up @@ -66,7 +65,35 @@ enum LanguageReadiness: Equatable, Sendable {
case checking
case installed
case alternativeInstalled
case preferredUnsupported
case alternativeDownloadRequired
case downloadRequired
case unsupported
case sameLanguage

// MARK: Internal

var needsLanguageDownload: Bool {
switch self {
case .downloadRequired,
.alternativeInstalled,
.alternativeDownloadRequired: true
default: false
}
}

/// An installed fallback is usable but is not readiness of the selected mode.
static func resolve(preferred: LanguageAvailability.Status, alternative: LanguageAvailability.Status) -> Self {
switch (preferred, alternative) {
case (.installed, _): .installed
case (.supported, .installed): .alternativeInstalled
case (.unsupported, .installed): .preferredUnsupported
case (.unsupported, .supported): .alternativeDownloadRequired
case (.supported, .supported),
(.supported, .unsupported): .downloadRequired
case (.unsupported, .unsupported): .unsupported
default: .unchecked
}
}

}
22 changes: 20 additions & 2 deletions Sources/Onboarding/OnboardingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ struct OnboardingView: View {
languageReadiness
Text("This checks only this language pair. Your source-language setting stays unchanged.")
.font(.caption).foregroundStyle(.secondary)
if store.modelReadiness == .downloadRequired {
if store.modelReadiness.needsLanguageDownload {
Text(
"Download the languages you want to translate from and into. For English → Korean, download both English and Korean."
)
Expand Down Expand Up @@ -168,7 +168,25 @@ struct OnboardingView: View {
Label("Ready to translate this language pair.", systemImage: "checkmark.circle.fill").foregroundStyle(.green)

case .alternativeInstalled:
Label("Ready using another installed translation mode.", systemImage: "checkmark.circle.fill").foregroundStyle(.green)
VStack(alignment: .leading, spacing: 6) {
Label("Download languages for the selected translation mode.", systemImage: "exclamationmark.triangle.fill")
.foregroundStyle(.orange)
Text("You can translate now using another installed mode.").font(.callout).foregroundStyle(.secondary)
}

case .preferredUnsupported:
VStack(alignment: .leading, spacing: 6) {
Label("The selected translation mode does not support this language pair.", systemImage: "exclamationmark.triangle.fill")
.foregroundStyle(.orange)
Text("You can translate now using another installed mode.").font(.callout).foregroundStyle(.secondary)
}

case .alternativeDownloadRequired:
VStack(alignment: .leading, spacing: 6) {
Label("The selected translation mode does not support this language pair.", systemImage: "exclamationmark.triangle.fill")
.foregroundStyle(.orange)
Text("Download the languages to use another translation mode.").font(.callout).foregroundStyle(.secondary)
}

case .downloadRequired:
Label("Download these languages to start translating.", systemImage: "arrow.down.circle").foregroundStyle(.orange)
Expand Down
Loading