From 73cb3e1855d25173fd7d5a7a44c1871998598ce9 Mon Sep 17 00:00:00 2001 From: jonasgaudian <43753916+jonasgaudian@users.noreply.github.com> Date: Fri, 13 Feb 2026 19:01:53 +0100 Subject: [PATCH] bump version to 0.4.1, sanitize API responses, and update string resources --- app/build.gradle.kts | 4 +-- .../translator/utils/ApiRequestHandler.kt | 25 +++++++++++-------- .../eu/gaudian/translator/utils/JsonHelper.kt | 18 +++++++------ .../viewmodel/DictionaryViewModel.kt | 2 +- app/src/main/res/values-de-rDE/arrays.xml | 24 ++++++++++++++---- app/src/main/res/values-de-rDE/strings.xml | 5 +++- app/src/main/res/values-pt-rBR/arrays.xml | 25 ++++++++++++++----- app/src/main/res/values-pt-rBR/strings.xml | 9 +++++-- app/src/main/res/values/strings.xml | 2 +- 9 files changed, 79 insertions(+), 35 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1a47b46..13c1c65 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -22,8 +22,8 @@ android { applicationId = "eu.gaudian.translator" minSdk = 28 targetSdk = 36 - versionCode = 21 - versionName = "0.4.0" + versionCode = 22 + versionName = "0.4.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/eu/gaudian/translator/utils/ApiRequestHandler.kt b/app/src/main/java/eu/gaudian/translator/utils/ApiRequestHandler.kt index 295db86..5dd2e9e 100644 --- a/app/src/main/java/eu/gaudian/translator/utils/ApiRequestHandler.kt +++ b/app/src/main/java/eu/gaudian/translator/utils/ApiRequestHandler.kt @@ -171,22 +171,27 @@ class ApiRequestHandler(private val apiManager: ApiManager, context: Context) { * Handles: * 1. Markdown code blocks (```json ... ```) * 2. Conversational wrapping ("Here is the JSON: ...") - * 3. Raw JSON + * 3. Think blocks (...) + * 4. Raw JSON */ private fun extractJsonFromResponse(text: String): String { val trimmed = text.trim() + // 0. First, strip any ... blocks (may contain newlines) + val thinkRegex = Regex("[\\s\\S]*?") + val textWithoutThink = thinkRegex.replace(trimmed, "").trim() + // 1. Try to find content within Markdown code blocks // This regex looks for ``` (optional json) ... content ... ``` val codeBlockRegex = Regex("```(?:json)?\\s*([\\s\\S]*?)\\s*```", RegexOption.IGNORE_CASE) - val match = codeBlockRegex.find(trimmed) + val match = codeBlockRegex.find(textWithoutThink) if (match != null) { return match.groupValues[1].trim() } // 2. If no code block is found, try to find the outermost JSON structure (Object or Array) - val firstBrace = trimmed.indexOf('{') - val firstBracket = trimmed.indexOf('[') + val firstBrace = textWithoutThink.indexOf('{') + val firstBracket = textWithoutThink.indexOf('[') var startIndex = -1 var endIndex = -1 @@ -195,18 +200,18 @@ class ApiRequestHandler(private val apiManager: ApiManager, context: Context) { // We pick whichever appears first if (firstBrace != -1 && (firstBracket == -1 || firstBrace < firstBracket)) { startIndex = firstBrace - endIndex = trimmed.lastIndexOf('}') + endIndex = textWithoutThink.lastIndexOf('}') } else if (firstBracket != -1) { startIndex = firstBracket - endIndex = trimmed.lastIndexOf(']') + endIndex = textWithoutThink.lastIndexOf(']') } if (startIndex != -1 && endIndex != -1 && endIndex > startIndex) { - return trimmed.substring(startIndex, endIndex + 1) + return textWithoutThink.substring(startIndex, endIndex + 1) } - // 3. Fallback: return the original text (parsing will likely fail if it's not valid JSON) - return trimmed + // 3. Fallback: return the text without think blocks (parsing will likely fail if it's not valid JSON) + return textWithoutThink } /** @@ -266,4 +271,4 @@ class ApiResponseException(message: String, cause: Throwable? = null) : Exceptio /** * Custom exception for API validation errors. */ -class ApiValidationException(message: String, cause: Throwable? = null) : Exception(message, cause) \ No newline at end of file +class ApiValidationException(message: String, cause: Throwable? = null) : Exception(message, cause) diff --git a/app/src/main/java/eu/gaudian/translator/utils/JsonHelper.kt b/app/src/main/java/eu/gaudian/translator/utils/JsonHelper.kt index d45c775..5dd8069 100644 --- a/app/src/main/java/eu/gaudian/translator/utils/JsonHelper.kt +++ b/app/src/main/java/eu/gaudian/translator/utils/JsonHelper.kt @@ -174,15 +174,19 @@ object JsonCleanUtil { private fun isolateJsonBlock(response: String): String { // Handle specific non-JSON tokens first + // Strip any ... blocks (may contain newlines) + val thinkRegex = Regex("[\\s\\S]*?") + val cleanedResponse = thinkRegex.replace(response, "").trim() + // The rest of the function operates on the cleaned response val markdownRegex = Regex("```json\\s*([\\s\\S]*?)\\s*```") - val markdownMatch = markdownRegex.find(response) + val markdownMatch = markdownRegex.find(cleanedResponse) if (markdownMatch != null && markdownMatch.groupValues.size > 1) { return markdownMatch.groupValues[1] } - val firstBrace = response.indexOf('{') - val firstBracket = response.indexOf('[') + val firstBrace = cleanedResponse.indexOf('{') + val firstBracket = cleanedResponse.indexOf('[') val startIndex = when { firstBrace == -1 -> firstBracket firstBracket == -1 -> firstBrace @@ -190,12 +194,12 @@ object JsonCleanUtil { } if (startIndex == -1) return "" - val lastBrace = response.lastIndexOf('}') - val lastBracket = response.lastIndexOf(']') + val lastBrace = cleanedResponse.lastIndexOf('}') + val lastBracket = cleanedResponse.lastIndexOf(']') val endIndex = maxOf(lastBrace, lastBracket) if (endIndex == -1 || startIndex >= endIndex) return "" - return response.substring(startIndex, endIndex + 1) + return cleanedResponse.substring(startIndex, endIndex + 1) } /** @@ -289,4 +293,4 @@ fun formatJsonForDisplay(json: String): String { } catch (_: Exception) { json // Fallback to raw JSON if formatting fails } -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/gaudian/translator/viewmodel/DictionaryViewModel.kt b/app/src/main/java/eu/gaudian/translator/viewmodel/DictionaryViewModel.kt index b57a6fe..28d8e53 100644 --- a/app/src/main/java/eu/gaudian/translator/viewmodel/DictionaryViewModel.kt +++ b/app/src/main/java/eu/gaudian/translator/viewmodel/DictionaryViewModel.kt @@ -537,7 +537,7 @@ class DictionaryViewModel @Inject constructor( showErrorMessage( getApplication().getString( R.string.text_failed_to_fetch_manifest, - e.message + // e.message Let's not include that part here, since it would show the server IP to the user )) } } diff --git a/app/src/main/res/values-de-rDE/arrays.xml b/app/src/main/res/values-de-rDE/arrays.xml index c19f14f..8e9df96 100644 --- a/app/src/main/res/values-de-rDE/arrays.xml +++ b/app/src/main/res/values-de-rDE/arrays.xml @@ -1,13 +1,10 @@ - + Exercise Example Prompts - Version 0.3.0 \n• CSV-Import für Vokabeln aktiviert\n• Option, für einige unterstützte Sprachen einen Übersetzungsserver statt KI-Modelle zu nutzen\n• UI-Fehlerbehebungen \n• Anzeige der Worthäufigkeit \n• Leistungsoptimierungen \n• Verbesserte Übersetzungen (Deutsch und Portugiesisch) Version 0.4.0 \n• Wörterbuch-Download hinzugefügt (Beta) \n• Verbesserungen der Benutzeroberfläche \n• Fehlerbehebungen \n• Neugestaltete Vokabelkarte mit verbesserter UI \n• Mehr vorkonfigurierte Anbieter \n• Verbesserte Leistung - - word_class_gender @@ -22,7 +19,6 @@ idioms grammatical_features_prepositions - Wortart und Genus (bei Nomen) Deklination (bei Nomen) @@ -36,4 +32,22 @@ Redewendungen Grammatikalische Merkmale (bei Präpositionen) + Alles übersetzen, ohne etwas hinzuzufügen. + Ersetze höfliche Pronomen Sie (formell) durch "du". + Mach es sehr formell. + Mach es informell und füge ein Emoji hinzu. + + Grundlegende Begrüßungen + Unregelmäßige Verben + Vokabular am Flughafen + Wie man einen Kaffee bestellt + Idiomatische Ausdrücke + + Verwende lateinamerikanisches Spanisch + Vermeide lange Wörter + Vermeide Sätze + Enthält viele Verben und Adjektive + Verwende informelle Sprache + + diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index af6f137..13f8276 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -696,7 +696,6 @@ Einige Wörterbücher konnten nicht gelöscht werden Fehler beim Herunterladen des Wörterbuchs: %1$s Etymologie konnte nicht abgerufen werden - Fehler beim Abrufen des Manifests: %1$s Video beenden und Übung starten Verwaistes File erfolgreich gelöscht Wähle zuerst eine Wörterbuch-Sprache aus. @@ -871,5 +870,9 @@ Auto Cycle (Dev) Neu generieren Vorlesen + Fehler beim Abrufen der Download-Informationen zu verfügbaren Wörterbüchern: %1$s + Setze ein Modell für die Übersetzung und gib optionale Anweisungen, wie übersetzt werden soll. + Alle Kategorien + Setze ein Modell zum Generieren von Wörterbuchinhalten und gib optionale Anweisungen. diff --git a/app/src/main/res/values-pt-rBR/arrays.xml b/app/src/main/res/values-pt-rBR/arrays.xml index cbac903..9884bf6 100644 --- a/app/src/main/res/values-pt-rBR/arrays.xml +++ b/app/src/main/res/values-pt-rBR/arrays.xml @@ -1,7 +1,6 @@ - + Exercise Example Prompts - word_class_gender @@ -16,7 +15,6 @@ idioms grammatical_features_prepositions - Classe da palavra e gênero (para substantivos) Declinação (para substantivos) @@ -30,11 +28,26 @@ Expressões idiomáticas Recursos gramaticais (para preposições) - Versão 0.3.0 \n• Habilitada a importação de vocabulário via CSV\n• Opção para usar um servidor de tradução em vez de modelos de IA para alguns idiomas suportados\n• Correções de bugs na interface \n• Exibição da frequência de palavras \n• Otimizações de desempenho \n• Traduções melhoradas (Alemão e Português) Versão 0.4.0 \n• Adicionado download de dicionário (beta) \n• Melhorias na interface \n• Correções de bugs \n• Cartão de vocabulário redesenhado com interface melhorada \n• Mais provedores pré-configurados \n• Desempenho melhorado - - + Traduzir tudo sem adicionar mais nada + Usa o pronome de "tu" em vez do formal "você/vos/vous" + Faz tudo muito formal e adicione um ponto final + Faz tudo informal + + Saudação básica + Verbos irregulares + Vocabulário no aeroporto + Como pedir um café + Expressões idiomáticas + + Usar espanhol latino-americano + Evitar palavras longas + Evitar frases + Incluir muitos verbos e adjetivos + Usar linguagem informal + + diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index f5ba5f0..8de65d3 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -689,7 +689,6 @@ Falhou ao excluir alguns dicionários Falhou ao baixar dicionário: %1$s Falhou ao buscar etimologia - Falhou ao buscar manifesto: %1$s Terminar Vídeo e Começar Exercício Dica Sem Dados Disponíveis @@ -705,7 +704,6 @@ Excluir Item do Vocabulário? Tem certeza de que deseja excluir este item do vocabulário? Idioma de Origem - Chutando Ortografia Múltipla Escolha @@ -867,5 +865,12 @@ Auto Ciclo (Dev) Regenerar Ler em Voz Alta + Direção do idioma + Idioma de destino + Falha ao buscar informações de download sobre dicionários disponíveis: %1$s + Defina o modelo para tradução e dê instruções opcionais sobre como traduzir. + Você pode definir uma preferência opcional sobre qual idioma deve vir primeiro ou segundo. + Todas as Categorias + Defina um modelo para gerar conteúdo do dicionário e dê instruções opcionais. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fc47f97..031f598 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -818,7 +818,7 @@ Failed to delete some dictionaries Failed to download dictionary: %1$s Failed to fetch etymology - Failed to fetch manifest: %1$s + Failed to fetch download information about available dictionaries: %1$s Failed to get translations: %1$s False Favorites