WIP non-working commit
This commit is contained in:
@@ -14,14 +14,32 @@ struct TranslateView: View {
|
|||||||
let size: EventViewKind
|
let size: EventViewKind
|
||||||
|
|
||||||
@State var checkingTranslationStatus: Bool = false
|
@State var checkingTranslationStatus: Bool = false
|
||||||
@State var currentLanguage: String = "en"
|
@State var translatable: Bool = true
|
||||||
@State var noteLanguage: String? = nil
|
|
||||||
@State var show_translated_note: Bool = false
|
@State var noteLanguage: String?
|
||||||
@State var translated_artifacts: NoteArtifacts? = nil
|
@State var show_translated_note: Bool
|
||||||
@State var translatable: Bool = false
|
@State var translated_artifacts: NoteArtifacts?
|
||||||
|
|
||||||
let preferredLanguages = Set(Locale.preferredLanguages.map { localeToLanguage($0) })
|
let preferredLanguages = Set(Locale.preferredLanguages.map { localeToLanguage($0) })
|
||||||
|
|
||||||
|
init(damus_state: DamusState, event: NostrEvent, size: EventViewKind) {
|
||||||
|
self.damus_state = damus_state
|
||||||
|
self.event = event
|
||||||
|
self.size = size
|
||||||
|
self._noteLanguage = State(initialValue: damus_state.translations.detectLanguage(event, state: damus_state))
|
||||||
|
|
||||||
|
if let translationWithLanguage = damus_state.translations.cachedTranslation(event) {
|
||||||
|
self._noteLanguage = State(initialValue: translationWithLanguage.language)
|
||||||
|
|
||||||
|
let translatedBlocks = event.get_blocks(content: translationWithLanguage.translation)
|
||||||
|
self._translated_artifacts = State.init(initialValue: render_blocks(blocks: translatedBlocks, profiles: damus_state.profiles, privkey: damus_state.keypair.privkey))
|
||||||
|
} else {
|
||||||
|
self._translated_artifacts = State(initialValue: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
self._show_translated_note = State(initialValue: damus_state.settings.auto_translate)
|
||||||
|
}
|
||||||
|
|
||||||
var TranslateButton: some View {
|
var TranslateButton: some View {
|
||||||
Button(NSLocalizedString("Translate Note", comment: "Button to translate note from different language.")) {
|
Button(NSLocalizedString("Translate Note", comment: "Button to translate note from different language.")) {
|
||||||
show_translated_note = true
|
show_translated_note = true
|
||||||
@@ -42,8 +60,9 @@ struct TranslateView: View {
|
|||||||
let translationWithLanguage = await damus_state.translations.translate(event, state: damus_state)
|
let translationWithLanguage = await damus_state.translations.translate(event, state: damus_state)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
guard translationWithLanguage != nil else {
|
guard translationWithLanguage != nil else {
|
||||||
noteLanguage = currentLanguage
|
noteLanguage = damus_state.translations.targetLanguage
|
||||||
checkingTranslationStatus = false
|
checkingTranslationStatus = false
|
||||||
|
show_translated_note = false
|
||||||
translatable = false
|
translatable = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -54,6 +73,8 @@ struct TranslateView: View {
|
|||||||
let translatedBlocks = event.get_blocks(content: translationWithLanguage!.translation)
|
let translatedBlocks = event.get_blocks(content: translationWithLanguage!.translation)
|
||||||
translated_artifacts = render_blocks(blocks: translatedBlocks, profiles: damus_state.profiles, privkey: damus_state.keypair.privkey)
|
translated_artifacts = render_blocks(blocks: translatedBlocks, profiles: damus_state.profiles, privkey: damus_state.keypair.privkey)
|
||||||
|
|
||||||
|
translatable = true
|
||||||
|
|
||||||
checkingTranslationStatus = false
|
checkingTranslationStatus = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,11 +93,15 @@ struct TranslateView: View {
|
|||||||
|
|
||||||
func MainContent(note_lang: String) -> some View {
|
func MainContent(note_lang: String) -> some View {
|
||||||
return Group {
|
return Group {
|
||||||
let languageName = Locale.current.localizedString(forLanguageCode: note_lang)
|
if translatable {
|
||||||
if let languageName, let translated_artifacts, show_translated_note {
|
let languageName = Locale.current.localizedString(forLanguageCode: note_lang)
|
||||||
Translated(lang: languageName, artifacts: translated_artifacts)
|
if let languageName, let translated_artifacts, show_translated_note {
|
||||||
} else if !damus_state.settings.auto_translate {
|
Translated(lang: languageName, artifacts: translated_artifacts)
|
||||||
TranslateButton
|
} else if !damus_state.settings.auto_translate {
|
||||||
|
TranslateButton
|
||||||
|
} else {
|
||||||
|
EmptyView()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
EmptyView()
|
EmptyView()
|
||||||
}
|
}
|
||||||
@@ -85,25 +110,17 @@ struct TranslateView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
if let note_lang = noteLanguage, noteLanguage != currentLanguage {
|
if let note_lang = noteLanguage, note_lang != damus_state.translations.targetLanguage {
|
||||||
MainContent(note_lang: note_lang)
|
MainContent(note_lang: note_lang)
|
||||||
|
.task {
|
||||||
|
if show_translated_note {
|
||||||
|
processTranslation()
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Text("")
|
Text("")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.task {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
currentLanguage = damus_state.translations.targetLanguage
|
|
||||||
noteLanguage = damus_state.translations.detectLanguage(event, state: damus_state)
|
|
||||||
translatable = damus_state.translations.shouldTranslate(event, state: damus_state)
|
|
||||||
|
|
||||||
let autoTranslate = damus_state.settings.auto_translate
|
|
||||||
if autoTranslate {
|
|
||||||
processTranslation()
|
|
||||||
}
|
|
||||||
show_translated_note = autoTranslate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,29 @@ class Translations: ObservableObject {
|
|||||||
return language
|
return language
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns true if the given translation is effectively the same as the original note, ignoring whitespaces and new lines.
|
||||||
|
*/
|
||||||
|
private func translationSameAsOriginal(_ translation: String, event: NostrEvent, state: DamusState) -> Bool {
|
||||||
|
return translation.trimmingCharacters(in: .whitespacesAndNewlines) == event.get_content(state.keypair.privkey).trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasCachedTranslation(_ event: NostrEvent) -> Bool {
|
||||||
|
return languages[event] != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func cachedTranslation(_ event: NostrEvent) -> TranslationWithLanguage? {
|
||||||
|
if let cachedLanguage = languages[event] {
|
||||||
|
if let cachedTranslation = translations[event] {
|
||||||
|
return TranslationWithLanguage(translation: cachedTranslation, language: cachedLanguage)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func translate(_ event: NostrEvent, state: DamusState) async -> TranslationWithLanguage? {
|
func translate(_ event: NostrEvent, state: DamusState) async -> TranslationWithLanguage? {
|
||||||
guard shouldTranslate(event, state: state) else {
|
guard shouldTranslate(event, state: state) else {
|
||||||
return nil
|
return nil
|
||||||
@@ -65,30 +88,29 @@ class Translations: ObservableObject {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
let translationWithLanguage: TranslationWithLanguage
|
if languages[event] != nil {
|
||||||
|
return cachedTranslation(event)
|
||||||
if let cachedTranslation = translations[event] {
|
|
||||||
translationWithLanguage = TranslationWithLanguage(translation: cachedTranslation, language: noteLanguage)
|
|
||||||
} else {
|
|
||||||
do {
|
|
||||||
guard let _translationWithLanguage = try await translator.translate(event.get_content(state.keypair.privkey), from: noteLanguage, to: targetLanguage) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
translationWithLanguage = _translationWithLanguage
|
|
||||||
translations[event] = translationWithLanguage.translation
|
|
||||||
languages[event] = translationWithLanguage.language
|
|
||||||
} catch {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the translated content is identical to the original content, don't return the translation.
|
do {
|
||||||
if translationWithLanguage.translation == event.get_content(state.keypair.privkey) {
|
guard let translationWithLanguage = try await translator.translate(event.get_content(state.keypair.privkey), from: noteLanguage, to: targetLanguage) else {
|
||||||
languages[event] = targetLanguage
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the translated content is identical to the original content, don't return the translation.
|
||||||
|
if translationSameAsOriginal(translationWithLanguage.translation, event: event, state: state) {
|
||||||
|
// Nil out the translation as it's the same as the original.
|
||||||
|
translations[event] = nil
|
||||||
|
// Leave an entry so that we don't attempt to translate it again in the future.
|
||||||
|
languages[event] = targetLanguage
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
translations[event] = translationWithLanguage.translation
|
||||||
|
languages[event] = translationWithLanguage.language
|
||||||
|
return translationWithLanguage
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
return nil
|
return nil
|
||||||
} else {
|
|
||||||
return translationWithLanguage
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,18 +121,30 @@ class Translations: ObservableObject {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Avoid translating if no translation service is configured.
|
||||||
|
switch settings.translation_service {
|
||||||
|
case .none:
|
||||||
|
return false
|
||||||
|
case .libretranslate:
|
||||||
|
if URLComponents(string: settings.libretranslate_url) == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case .deepl:
|
||||||
|
if settings.deepl_api_key == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If translation was attempted before, use the results of the cached translation to determine if it should be shown.
|
||||||
|
if languages[event] != nil {
|
||||||
|
return translations[event] != nil
|
||||||
|
}
|
||||||
|
|
||||||
// Avoid translating notes if language cannot be detected or if it is in one of the user's preferred languages.
|
// Avoid translating notes if language cannot be detected or if it is in one of the user's preferred languages.
|
||||||
guard let noteLanguage = detectLanguage(event, state: state), !preferredLanguages.contains(noteLanguage) else {
|
guard let noteLanguage = detectLanguage(event, state: state), !preferredLanguages.contains(noteLanguage) else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
switch settings.translation_service {
|
return true
|
||||||
case .none:
|
|
||||||
return false
|
|
||||||
case .libretranslate:
|
|
||||||
return URLComponents(string: settings.libretranslate_url) != nil
|
|
||||||
case .deepl:
|
|
||||||
return settings.deepl_api_key != ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ struct NoteContentView: View {
|
|||||||
let size: EventViewKind
|
let size: EventViewKind
|
||||||
let preview_height: CGFloat?
|
let preview_height: CGFloat?
|
||||||
let options: EventViewOptions
|
let options: EventViewOptions
|
||||||
|
let translatable: Bool
|
||||||
|
|
||||||
@State var artifacts: NoteArtifacts
|
@State var artifacts: NoteArtifacts
|
||||||
@State var preview: LinkViewRepresentable?
|
@State var preview: LinkViewRepresentable?
|
||||||
@@ -39,6 +40,7 @@ struct NoteContentView: View {
|
|||||||
self.show_images = show_images
|
self.show_images = show_images
|
||||||
self.size = size
|
self.size = size
|
||||||
self.options = options
|
self.options = options
|
||||||
|
self.translatable = damus_state.translations.shouldTranslate(event, state: damus_state)
|
||||||
self._artifacts = State(initialValue: artifacts)
|
self._artifacts = State(initialValue: artifacts)
|
||||||
self.preview_height = lookup_cached_preview_size(previews: damus_state.previews, evid: event.id)
|
self.preview_height = lookup_cached_preview_size(previews: damus_state.previews, evid: event.id)
|
||||||
self._preview = State(initialValue: load_cached_preview(previews: damus_state.previews, evid: event.id))
|
self._preview = State(initialValue: load_cached_preview(previews: damus_state.previews, evid: event.id))
|
||||||
@@ -100,11 +102,13 @@ struct NoteContentView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if with_padding {
|
if translatable {
|
||||||
translateView
|
if with_padding {
|
||||||
.padding(.horizontal)
|
translateView
|
||||||
} else {
|
.padding(.horizontal)
|
||||||
translateView
|
} else {
|
||||||
|
translateView
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if show_images && artifacts.images.count > 0 {
|
if show_images && artifacts.images.count > 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user