Remove the DeepL fallback

The DeepL fallback for the instance translation service is removed,
error messages are shown if a translation fails.
This commit is contained in:
Paul Schuetz 2024-05-13 11:34:17 +02:00
parent 8f06719b23
commit b4a1b09864
No known key found for this signature in database
GPG key ID: 4FDE1FB89050039E
7 changed files with 243 additions and 174 deletions

View file

@ -31,7 +31,9 @@ struct SettingsTabs: View {
@Binding var popToRootTab: Tab
let isModal: Bool
@State private var startingPoint: SettingsStartingPoint? = nil
var body: some View {
NavigationStack(path: $routerPath.path) {
Form {
@ -64,6 +66,32 @@ struct SettingsTabs: View {
}
.withAppRouter()
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
.onAppear {
startingPoint = RouterPath.settingsStartingPoint
RouterPath.settingsStartingPoint = nil
}
.navigationDestination(item: $startingPoint) { targetView in
switch targetView {
case .display:
DisplaySettingsView()
case .haptic:
HapticSettingsView()
case .remoteTimelines:
RemoteTimelinesSettingView()
case .tagGroups:
TagsGroupSettingView()
case .recentTags:
RecenTagsSettingView()
case .content:
ContentSettingsView()
case .swipeActions:
SwipeActionsSettingsView()
case .tabAndSidebarEntries:
EmptyView()
case .translation:
TranslationSettingsView()
}
}
}
.onAppear {
routerPath.client = client

View file

@ -18412,6 +18412,126 @@
}
}
},
"action.cancel" : {
"comment" : "MARK: Common strings",
"extractionState" : "stale",
"localizations" : {
"be" : {
"stringUnit" : {
"state" : "translated",
"value" : "Скасаваць"
}
},
"ca" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cancel·la"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Abbrechen"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cancel"
}
},
"en-GB" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cancel"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cancelar"
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Utzi"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Annuler"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Annulla"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "キャンセル"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "취소"
}
},
"nb" : {
"stringUnit" : {
"state" : "translated",
"value" : "Avbryt"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Annuleer"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Anuluj"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cancelar"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "İptal Et"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Відміна"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "取消"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "取消"
}
}
}
},
"action.delete" : {
"extractionState" : "manual",
"localizations" : {
@ -20304,6 +20424,40 @@
}
}
},
"alert.translation-error.deepl" : {
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "DeepL konnte nicht erreicht werden!\nIst der API-Schlüssel korrekt?"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "DeepL couldn't be reached!\nIs the API Key correct?"
}
}
}
},
"alert.translation-error.instance" : {
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Der Übersetzung-Service deiner Instanz konnte nicht erreicht werden!"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The Translation Service of your Instance couldn't be reached!"
}
}
}
},
"An error occured while posting to Mastodon, please try again." : {
"localizations" : {
"de" : {
@ -81080,126 +81234,6 @@
}
}
}
},
"action.cancel" : {
"comment" : "MARK: Common strings",
"extractionState" : "stale",
"localizations" : {
"be" : {
"stringUnit" : {
"state" : "translated",
"value" : "Скасаваць"
}
},
"ca" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cancel·la"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Abbrechen"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cancel"
}
},
"en-GB" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cancel"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cancelar"
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Utzi"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Annuler"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Annulla"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "キャンセル"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "취소"
}
},
"nb" : {
"stringUnit" : {
"state" : "translated",
"value" : "Avbryt"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Annuleer"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Anuluj"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cancelar"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "İptal Et"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Відміна"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "取消"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "取消"
}
}
}
},
"Visibility" : {
"localizations" : {
@ -81223,4 +81257,4 @@
}
},
"version" : "1.0"
}
}

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>DEEPL_SECRET</key>
<string>NICE_TRY_AGAIN</string>
</dict>
</plist>

View file

@ -115,6 +115,18 @@ public enum SheetDestination: Identifiable, Hashable {
}
}
public enum SettingsStartingPoint {
case display
case haptic
case remoteTimelines
case tagGroups
case recentTags
case content
case swipeActions
case tabAndSidebarEntries
case translation
}
@MainActor
@Observable public class RouterPath {
public var client: Client?
@ -123,6 +135,8 @@ public enum SheetDestination: Identifiable, Hashable {
public var path: [RouterDestination] = []
public var presentedSheet: SheetDestination?
public static var settingsStartingPoint: SettingsStartingPoint? = nil
public init() {}
public func navigate(to: RouterDestination) {

View file

@ -12,20 +12,8 @@ public struct DeepLClient: Sendable {
"https://api\(deeplUserAPIFree && (deeplUserAPIKey != nil) ? "-free" : "").deepl.com/v2/translate"
}
private var APIKey: String {
if let deeplUserAPIKey {
return deeplUserAPIKey
}
if let path = Bundle.main.path(forResource: "Secret", ofType: "plist") {
let secret = NSDictionary(contentsOfFile: path)
return secret?["DEEPL_SECRET"] as? String ?? ""
}
return ""
}
private var authorizationHeaderValue: String {
"DeepL-Auth-Key \(APIKey)"
"DeepL-Auth-Key \(deeplUserAPIKey ?? "")"
}
public struct Response: Decodable {
@ -49,26 +37,22 @@ public struct DeepLClient: Sendable {
}
public func request(target: String, text: String) async throws -> Translation {
do {
var components = URLComponents(string: endpoint)!
var queryItems: [URLQueryItem] = []
queryItems.append(.init(name: "text", value: text))
queryItems.append(.init(name: "target_lang", value: target.uppercased()))
components.queryItems = queryItems
var request = URLRequest(url: components.url!)
request.httpMethod = "POST"
request.setValue(authorizationHeaderValue, forHTTPHeaderField: "Authorization")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let (result, _) = try await URLSession.shared.data(for: request)
let response = try decoder.decode(Response.self, from: result)
if let translation = response.translations.first {
return .init(content: translation.text.removingPercentEncoding ?? "",
detectedSourceLanguage: translation.detectedSourceLanguage,
provider: "DeepL.com")
}
throw DeepLError.notFound
} catch {
throw error
var components = URLComponents(string: endpoint)!
var queryItems: [URLQueryItem] = []
queryItems.append(.init(name: "text", value: text))
queryItems.append(.init(name: "target_lang", value: target.uppercased()))
components.queryItems = queryItems
var request = URLRequest(url: components.url!)
request.httpMethod = "POST"
request.setValue(authorizationHeaderValue, forHTTPHeaderField: "Authorization")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let (result, _) = try await URLSession.shared.data(for: request)
let response = try decoder.decode(Response.self, from: result)
if let translation = response.translations.first {
return .init(content: translation.text.removingPercentEncoding ?? "",
detectedSourceLanguage: translation.detectedSourceLanguage,
provider: "DeepL.com")
}
throw DeepLError.notFound
}
}

View file

@ -28,6 +28,7 @@ public struct StatusRowView: View {
@Environment(\.accessibilityVoiceOverEnabled) private var accessibilityVoiceOverEnabled
@Environment(\.isStatusFocused) private var isFocused
@Environment(\.indentationLevel) private var indentationLevel
@Environment(RouterPath.self) private var routerPath: RouterPath
@Environment(QuickLook.self) private var quickLook
@Environment(Theme.self) private var theme
@ -232,6 +233,20 @@ public struct StatusRowView: View {
StatusDataControllerProvider.shared.dataController(for: viewModel.finalStatus,
client: viewModel.client)
)
.alert("alert.translation-error.deepl", isPresented: $viewModel.deeplTranslationError) {
Button("alert.button.ok", role: .cancel) {}
Button("settings.general.translate") {
RouterPath.settingsStartingPoint = .translation
routerPath.presentedSheet = .settings
}
}
.alert("alert.translation-error.instance", isPresented: $viewModel.instanceTranslationError) {
Button("alert.button.ok", role: .cancel) {}
Button("settings.general.translate") {
RouterPath.settingsStartingPoint = .translation
routerPath.presentedSheet = .settings
}
}
#if canImport(_Translation_SwiftUI)
.addTranslateView(isPresented: $viewModel.showAppleTranslation, text: viewModel.finalStatus.content.asRawText)
#endif

View file

@ -40,6 +40,8 @@ import SwiftUI
}
}
}
var deeplTranslationError = false
var instanceTranslationError = false
private(set) var actionsAccountsFetched: Bool = false
var favoriters: [Account] = []
@ -316,21 +318,21 @@ import SwiftUI
isLoadingTranslation = true
}
if preferredTranslationType != .useDeepl {
do {
// We first use instance translation API if available.
let translation: Translation = try await client.post(endpoint: Statuses.translate(id: finalStatus.id,
let translation: Translation? = try? await client.post(endpoint: Statuses.translate(id: finalStatus.id,
lang: userLang))
withAnimation {
self.translation = translation
isLoadingTranslation = false
self.translation = translation
isLoadingTranslation = false
}
return
} catch {}
if translation == nil {
instanceTranslationError = true
}
} else {
await translateWithDeepL(userLang: userLang)
if translation == nil {
deeplTranslationError = true
}
}
// If not or fail we use Ice Cubes own DeepL client.
await translateWithDeepL(userLang: userLang)
}
func translateWithDeepL(userLang: String) async {