mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2025-01-27 04:54:55 +01:00
Allow translation of an account bio/note (#1276)
The bio (note) of an account can now be translated via DeepL. If the user has put in his own DeepL API key, that is used, otherwise, the standard one is used. See #1267 Signed-off-by: Paul Schuetz <pa.schuetz@web.de>
This commit is contained in:
parent
a08587643d
commit
da0b92e13d
@ -150,6 +150,17 @@ public struct AccountDetailContextMenu: View {
|
||||
Divider()
|
||||
}
|
||||
|
||||
if let lang = preferences.serverPreferences?.postLanguage ?? Locale.current.language.languageCode?.identifier
|
||||
{
|
||||
Button {
|
||||
Task {
|
||||
await viewModel.translate(userLang: lang)
|
||||
}
|
||||
} label: {
|
||||
Label("status.action.translate", systemImage: "captions.bubble")
|
||||
}
|
||||
}
|
||||
|
||||
if viewModel.relationship?.following == true {
|
||||
Button {
|
||||
routerPath.presentedSheet = .listAddAccount(account: account)
|
||||
|
@ -202,12 +202,34 @@ struct AccountDetailHeaderView: View {
|
||||
routerPath.handle(url: url)
|
||||
})
|
||||
|
||||
if let translation = viewModel.translation, !viewModel.isLoadingTranslation {
|
||||
GroupBox {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text(translation.content.asSafeMarkdownAttributedString)
|
||||
.font(.scaledBody)
|
||||
Text(getLocalizedStringLabel(langCode: translation.detectedSourceLanguage, provider: translation.provider))
|
||||
.font(.footnote)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
|
||||
fieldsView
|
||||
}
|
||||
.padding(.horizontal, .layoutPadding)
|
||||
.offset(y: -40)
|
||||
}
|
||||
|
||||
private func getLocalizedStringLabel(langCode: String, provider: String) -> String {
|
||||
if let localizedLanguage = Locale.current.localizedString(forLanguageCode: langCode) {
|
||||
let format = NSLocalizedString("status.action.translated-label-from-%@-%@", comment: "")
|
||||
return String.localizedStringWithFormat(format, localizedLanguage, provider)
|
||||
} else {
|
||||
return "status.action.translated-label-\(provider)"
|
||||
}
|
||||
}
|
||||
|
||||
private func makeCustomInfoLabel(title: LocalizedStringKey, count: Int, needsBadge: Bool = false) -> some View {
|
||||
VStack {
|
||||
Text(count, format: .number.notation(.compactName))
|
||||
|
@ -83,6 +83,9 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
|
||||
}
|
||||
}
|
||||
|
||||
@Published var translation: Translation?
|
||||
@Published var isLoadingTranslation = false
|
||||
|
||||
private(set) var account: Account?
|
||||
private var tabTask: Task<Void, Never>?
|
||||
|
||||
@ -263,4 +266,22 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
|
||||
func statusDidAppear(status _: Models.Status) {}
|
||||
|
||||
func statusDidDisappear(status _: Status) {}
|
||||
|
||||
func translate(userLang: String) async {
|
||||
guard let account else { return }
|
||||
withAnimation {
|
||||
isLoadingTranslation = true
|
||||
}
|
||||
|
||||
let userAPIKey = DeepLUserAPIHandler.readIfAllowed()
|
||||
let userAPIFree = UserPreferences.shared.userDeeplAPIFree
|
||||
let deeplClient = DeepLClient(userAPIKey: userAPIKey, userAPIFree: userAPIFree)
|
||||
|
||||
let translation = try? await deeplClient.request(target: userLang, text: account.note.asRawText)
|
||||
|
||||
withAnimation {
|
||||
self.translation = translation
|
||||
isLoadingTranslation = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public struct StatusTranslation: Decodable {
|
||||
public struct Translation: Decodable {
|
||||
public let content: HTMLString
|
||||
public let detectedSourceLanguage: String
|
||||
public let provider: String
|
||||
@ -12,4 +12,4 @@ public struct StatusTranslation: Decodable {
|
||||
}
|
||||
}
|
||||
|
||||
extension StatusTranslation: Sendable {}
|
||||
extension Translation: Sendable {}
|
@ -48,7 +48,7 @@ public struct DeepLClient {
|
||||
deeplUserAPIFree = userAPIFree
|
||||
}
|
||||
|
||||
public func request(target: String, text: String) async throws -> StatusTranslation {
|
||||
public func request(target: String, text: String) async throws -> Translation {
|
||||
do {
|
||||
var components = URLComponents(string: endpoint)!
|
||||
var queryItems: [URLQueryItem] = []
|
||||
|
@ -21,7 +21,7 @@ public class StatusRowViewModel: ObservableObject {
|
||||
@Published var isEmbedLoading: Bool = false
|
||||
@Published var isFiltered: Bool = false
|
||||
|
||||
@Published var translation: StatusTranslation?
|
||||
@Published var translation: Translation?
|
||||
@Published var isLoadingTranslation: Bool = false
|
||||
@Published var showDeleteAlert: Bool = false
|
||||
|
||||
@ -294,7 +294,7 @@ public class StatusRowViewModel: ObservableObject {
|
||||
if !alwaysTranslateWithDeepl {
|
||||
do {
|
||||
// We first use instance translation API if available.
|
||||
let translation: StatusTranslation = 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
|
||||
|
Loading…
Reference in New Issue
Block a user