diff options
author | Obsidian <108832807+Obsidianninja11@users.noreply.github.com> | 2024-10-11 10:23:27 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-11 20:23:27 +0200 |
commit | 92291e61cbbdc05736288aef1743ee1c667da6fa (patch) | |
tree | 2184e58377869d4e76389c8b285fba9cc7caaf99 | |
parent | 8a0105f4ad3964d1c8977fa8b09c75df33a74c74 (diff) | |
download | skyhanni-92291e61cbbdc05736288aef1743ee1c667da6fa.tar.gz skyhanni-92291e61cbbdc05736288aef1743ee1c667da6fa.tar.bz2 skyhanni-92291e61cbbdc05736288aef1743ee1c667da6fa.zip |
Fix/Improvement: Translator feature (#2693)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
4 files changed, 95 insertions, 74 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt index 44565aa95..bd94a1658 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -252,12 +252,12 @@ object Commands { ) { FarmingWeightDisplay.lookUpCommand(it) } registerCommand( "shcopytranslation", - "Copy the English translation of a message in another language to the clipboard.\n" + "Uses a 2 letter language code that can be found at the end of a translation message.", - ) { Translator.fromEnglish(it) } + "Copy the translation of a message in another language to your clipboard.\n" + "Uses a language code that can be found at the end of a translation message.", + ) { Translator.fromNativeLanguage(it) } registerCommand( "shtranslate", - "Translate a message in another language to English.", - ) { Translator.toEnglish(it) } + "Translate a message in another language to your language.", + ) { Translator.toNativeLanguage(it) } registerCommand( "shmouselock", "Lock/Unlock the mouse so it will no longer rotate the player (for farming)", @@ -619,6 +619,10 @@ object Commands { "shresetmineshaftpitystats", "Resets the mineshaft pity display stats", ) { MineshaftPityDisplay.fullResetCounter() } + registerCommand( + "shtranslateadvanced", + "Translates a message in an inputted language to another inputted language.", + ) { Translator.translateAdvancedCommand(it) } } private fun internalCommands() { diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/chat/TranslatorConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/chat/TranslatorConfig.java index 648afbd87..fdd678d0b 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/chat/TranslatorConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/chat/TranslatorConfig.java @@ -2,8 +2,10 @@ package at.hannibal2.skyhanni.config.features.chat; import at.hannibal2.skyhanni.config.FeatureToggle; import at.hannibal2.skyhanni.features.chat.translation.TranslatableLanguage; +import at.hannibal2.skyhanni.utils.OSUtils; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorButton; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDropdown; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorText; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; @@ -14,7 +16,7 @@ public class TranslatorConfig { @Expose @ConfigOption( name = "Translate On Click", - desc = "Click on a message to translate it to English.\n" + + desc = "Click on a message to translate it to your language.\n" + "Use §e/shcopytranslation§7 to translate from English.\n" + "§cTranslation is not guaranteed to be 100% accurate." ) @@ -22,7 +24,7 @@ public class TranslatorConfig { @FeatureToggle public boolean translateOnClick = false; - @ConfigOption(name = "Language Name", desc = "The name of the language selected below. Note that languages marked as unknown might still be supported.") + @ConfigOption(name = "Your Language", desc = "The language that messages should be translated to.") @Expose @ConfigEditorDropdown public Property<TranslatableLanguage> languageName = Property.of(TranslatableLanguage.ENGLISH); @@ -30,8 +32,18 @@ public class TranslatorConfig { @Expose @ConfigOption( name = "Language Code", - desc = "Enter a language code here to translate on chat click into another language. " + - "E.g. `es` for spanish or 'de' for german. Empty for english.") + desc = "If your language doesn't show in the dropdown, enter your language code here. " + + "E.g. 'es' for Spanish or 'de' for German. Empty will use English." + ) @ConfigEditorText public Property<String> languageCode = Property.of("en"); + + @ConfigOption( + name = "List of Language Codes", + desc = "A list of Google Translate's suppored language codes." + ) + @ConfigEditorButton(buttonText = "Open") + public Runnable langCodesURL = () -> OSUtils.openBrowser( + "https://cloud.google.com/translate/docs/languages#try-it-for-yourself" + ); } diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/translation/TranslatableLanguage.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/translation/TranslatableLanguage.kt index 13a19a1dc..7f5db80d1 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/translation/TranslatableLanguage.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/translation/TranslatableLanguage.kt @@ -34,8 +34,8 @@ enum class TranslatableLanguage(private val englishName: String, private val nat TAGALOG("Tagalog", "Tagalog", "tl"), // Major language in the Philippines PUNJABI("Punjabi", "ਪੰਜਾਬੀ", "pa"), // Significant in India and Pakistan - // 5. need better name - UNKNOWN("Unknown Language", "", ""), + // 5. Other Language + UNKNOWN("Other", "", ""), ; // Limit to 20 characters so that the text is not too small in the config diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/translation/Translator.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/translation/Translator.kt index 24809faac..ca827432f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/translation/Translator.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/translation/Translator.kt @@ -66,7 +66,7 @@ object Translator { if (text.isEmpty()) { config.languageName.set(TranslatableLanguage.ENGLISH) } else { - for (language in TranslatableLanguage.values()) { + for (language in TranslatableLanguage.entries) { if (language.languageCode.equals(text, ignoreCase = true)) { config.languageName.set(language) return@onToggle @@ -107,102 +107,107 @@ object Translator { * ] * ], * null, - * '"target language as a two-letter code following ISO 639-1"', + * '"target language as a (usually) two-letter code following ISO 639-1"', * ] */ - private fun getJSONResponse(urlString: String) = - APIUtils.getJSONResponseAsElement(urlString, false, "Google Translate API") + private fun getJSONResponse(urlString: String) = APIUtils.getJSONResponseAsElement(urlString, false, "Google Translate API") - private fun getTranslationToEnglish(message: String): String { - val url = - "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=en&dt=t&q=" + - URLEncoder.encode(message, "UTF-8") + fun getTranslation( + message: String, + targetLanguage: String, + sourceLanguage: String = "auto", + ): Array<String>? { + // TODO add &dj=1 to use named json + val url = "https://translate.googleapis.com/translate_a/single?client=gtx&dt=t&sl=$sourceLanguage&tl=$targetLanguage&q=" + + URLEncoder.encode(message, "UTF-8") var messageToSend = "" - val layer1 = getJSONResponse(url).asJsonArray - if (layer1.size() <= 2) return "Error!" + val fullResponse = getJSONResponse(url).asJsonArray + if (fullResponse.size() < 3) return null - val language = layer1[2].toString() - if (language == "\"en\"") return "Unable to translate!" - if (language.length != 4) return "Error!" + val language = fullResponse[2].toString() // the detected language the message is in + val sentences = fullResponse[0] as? JsonArray ?: return null - val layer2 = try { - layer1[0] as JsonArray - } catch (_: Exception) { - return "Error!" - } - - for (layer3 in layer2) { - val arrayLayer3 = layer3 as? JsonArray ?: continue - val sentence = arrayLayer3[0].toString() + for (rawSentence in sentences) { + val arrayPhrase = rawSentence as? JsonArray ?: continue + val sentence = arrayPhrase[0].toString() val sentenceWithoutQuotes = sentence.substring(1, sentence.length - 1) messageToSend = "$messageToSend$sentenceWithoutQuotes" } - messageToSend = "$messageToSend §7(Language: $language)" + messageToSend = URLDecoder.decode(messageToSend, "UTF-8").replace("\\", "") // Not sure if this is actually needed + return arrayOf(messageToSend, language) + } - return URLDecoder.decode(messageToSend, "UTF-8").replace("\\", "") + @Deprecated("Use toNativeLanguage() instead", ReplaceWith("Translator.toNativeLanguage(args)")) + fun toEnglish(args: Array<String>) { + toNativeLanguage(args) } - private fun getTranslationFromEnglish(message: String, lang: String): String { - val url = - "https://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=$lang&dt=t&q=" + - URLEncoder.encode(message, "UTF-8") - - val layer1 = getJSONResponse(url).asJsonArray - if (layer1.size() < 1) return "Error!" - val layer2 = layer1[0] as? JsonArray - - val firstSentence = (layer2?.get(0) as? JsonArray)?.get(0).toString() - var messageToSend = firstSentence.substring(0, firstSentence.length - 1) - if (layer2 != null) { - for (sentenceIndex in 1..<layer2.size()) { - val sentence = (layer2.get(sentenceIndex) as JsonArray).get(0).toString() - val sentenceWithoutQuotes = sentence.substring(1, sentence.length - 1) - messageToSend = "$messageToSend$sentenceWithoutQuotes" - } - } // The first translated sentence only has 1 extra char at the end, but sentences after it need 1 at the front and 1 at the end removed in the substring - messageToSend = messageToSend.substring(1, messageToSend.length) - return URLDecoder.decode(messageToSend, "UTF-8").replace("\\", "") + @Deprecated("Use fromNativeLanguage() instead", ReplaceWith("Translator.fromNativeLanguage(args)")) + fun fromEnglish(args: Array<String>) { + fromNativeLanguage(args) } - fun toEnglish(args: Array<String>) { + fun toNativeLanguage(args: Array<String>) { val message = args.joinToString(" ").removeColor() coroutineScope.launch { - var lang = config.languageCode.get() - val translation = if (lang.isEmpty()) { - getTranslationToEnglish(message) - } else { - getTranslationFromEnglish(message, lang) - } - if (message == translation) { - ChatUtils.userError("Translation is the same as the original message!") - return@launch - } + val translation = getTranslation(message, nativeLanguage()) + val translatedMessage = translation?.get(0) ?: "Error!" + val detectedLanguage = translation?.get(1) ?: "Error!" - if (translation == "Unable to translate!") { - ChatUtils.userError("Unable to translate message :( (is it in English?)") + if (message == translatedMessage) { + ChatUtils.userError("Translation is the same as the original message!") return@launch } - ChatUtils.chat("Found translation: §f$translation") + ChatUtils.clickableChat( + "Found translation: §f$translatedMessage", + onClick = { OSUtils.copyToClipboard(translatedMessage) }, + "§eClick to copy!\n§eOriginal message: §f$message §7(Language: $detectedLanguage)", + ) } } - fun fromEnglish(args: Array<String>) { - if (args.size < 2 || args[0].length != 2) { // args[0] is the language code - ChatUtils.userError("Usage: /shcopytranslation <two letter language code (at the end of a translation)> <message>") + fun fromNativeLanguage(args: Array<String>) { + if (args.size < 2) { + ChatUtils.userError("Usage: /shcopytranslation <language code (found at the end of a translation)> <message>") return } val language = args[0] val message = args.drop(1).joinToString(" ") coroutineScope.launch { - val translation = getTranslationFromEnglish(message, language) - ChatUtils.chat("Copied translation to clipboard: §f$translation") - OSUtils.copyToClipboard(translation) + val translation = getTranslation(message, language, nativeLanguage())?.get(0) ?: "Error!" + ChatUtils.clickableChat( + "Copied §f$language §etranslation to clipboard: §f$translation", + onClick = { OSUtils.copyToClipboard(translation) }, + "§eClick to copy!\n§eOriginal message: §f$message", + ) } } + fun translateAdvancedCommand(args: Array<String>) { + if (args.size < 3) { + ChatUtils.userError("Usage: /shtranslateadvanced <source lang code> <target lang code> <message>") + return + } + val sourceLanguage = args[0] + val targetLanguage = args[1] + val message = args.drop(2).joinToString(" ") + + val translation = getTranslation(message, sourceLanguage, targetLanguage) + val translatedMessage = translation?.get(0) ?: "Error!" + val detectedLanguage = if (sourceLanguage == "auto") " ${translation?.get(1) ?: "Error!"}" else "" + + ChatUtils.clickableChat( + "Found translation from sl: $sourceLanguage: §f$translatedMessage §7(tl: $targetLanguage)", + onClick = { OSUtils.copyToClipboard(translatedMessage) }, + "§eClick to copy!\n§eOriginal message: §f$message §7(sl: $sourceLanguage$detectedLanguage)", + ) + } + + fun nativeLanguage(): String = config.languageCode.get().ifEmpty { "en" } + fun isEnabled() = config.translateOnClick } |