From 24ff6058d5a27c776c307cb1ee55a8f574d918ad Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Sun, 19 Apr 2026 00:19:42 +0200 Subject: [PATCH] fixed ai workspace voice google issue --- modules/connectors/connectorVoiceGoogle.py | 48 ++++++++++++++----- modules/interfaces/interfaceVoiceObjects.py | 17 ++++--- .../serviceAgent/coreTools/_workspaceTools.py | 4 +- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/modules/connectors/connectorVoiceGoogle.py b/modules/connectors/connectorVoiceGoogle.py index aebede8a..1dc0912b 100644 --- a/modules/connectors/connectorVoiceGoogle.py +++ b/modules/connectors/connectorVoiceGoogle.py @@ -562,16 +562,34 @@ class ConnectorGoogleSpeech: """Google TTS WaveNet cost: ~$0.000004/char.""" return round(characterCount * 0.000004, 8) + @staticmethod + def _normalizeLanguageCode(code: Optional[str]) -> Optional[str]: + """Normalize a user/LLM-supplied language hint to an ISO-639-1 code or None. + + Google Cloud Translation v2 only accepts ISO codes (e.g. 'de', 'en') or + an omitted source for auto-detection. Strings like 'auto', '' or full + BCP-47 tags ('de-DE') would otherwise reach the API and trigger + '400 Invalid Value'. Centralising the mapping here keeps every caller + (tools, interface, internal pipelines) safe. + """ + if not code: + return None + normalized = code.strip().lower() + if not normalized or normalized in ("auto", "detect", "any", "*"): + return None + return normalized.split("-")[0] + async def translateText(self, text: str, targetLanguage: str = "en", - sourceLanguage: str = "de") -> Dict: + sourceLanguage: Optional[str] = None) -> Dict: """ Translate text using Google Cloud Translation API. - + Args: text: Text to translate - target_language: Target language code (e.g., 'en', 'de') - source_language: Source language code (e.g., 'de', 'en') - + targetLanguage: Target language code (e.g., 'en', 'de') + sourceLanguage: Source language code (e.g., 'de', 'en'); pass None + or 'auto' for Google's auto-detection. + Returns: Dict containing translated text and metadata """ @@ -583,14 +601,18 @@ class ConnectorGoogleSpeech: "translated_text": "", "error": "Empty text provided" } - - logger.info(f"🌐 Translating: '{text}' ({sourceLanguage} -> {targetLanguage})") - - # Perform translation + + normalizedSource = self._normalizeLanguageCode(sourceLanguage) + normalizedTarget = self._normalizeLanguageCode(targetLanguage) or "en" + logger.info( + f"🌐 Translating: '{text}' " + f"({normalizedSource or 'auto'} -> {normalizedTarget})" + ) + result = self.translate_client.translate( text, - source_language=sourceLanguage, - target_language=targetLanguage + source_language=normalizedSource, + target_language=normalizedTarget, ) translatedText = result['translatedText'] @@ -708,8 +730,8 @@ class ConnectorGoogleSpeech: # Step 2: Translation translationResult = await self.translateText( text=originalText, - sourceLanguage=fromLanguage.split('-')[0], # Convert 'de-DE' to 'de' - targetLanguage=toLanguage.split('-')[0] # Convert 'en-US' to 'en' + sourceLanguage=fromLanguage, + targetLanguage=toLanguage, ) if not translationResult["success"]: diff --git a/modules/interfaces/interfaceVoiceObjects.py b/modules/interfaces/interfaceVoiceObjects.py index 38807bac..69962259 100644 --- a/modules/interfaces/interfaceVoiceObjects.py +++ b/modules/interfaces/interfaceVoiceObjects.py @@ -181,21 +181,26 @@ class VoiceObjects: "error": str(e) } - async def translateText(self, text: str, sourceLanguage: str = "de", + async def translateText(self, text: str, + sourceLanguage: Optional[str] = None, targetLanguage: str = "en") -> Dict[str, Any]: """ Translate text using Google Cloud Translation API. - + Args: text: Text to translate - sourceLanguage: Source language code (e.g., 'de', 'en') - targetLanguage: Target language code (e.g., 'en', 'de') - + sourceLanguage: Source language ISO code (e.g. 'de', 'en'); pass None + or 'auto' to let Google auto-detect. + targetLanguage: Target language ISO code (e.g. 'en', 'de') + Returns: Dict containing translated text and metadata """ try: - logger.info(f"🌐 Translation request: '{text}' ({sourceLanguage} -> {targetLanguage})") + logger.info( + f"🌐 Translation request: '{text}' " + f"({sourceLanguage or 'auto'} -> {targetLanguage})" + ) if not text.strip(): return { diff --git a/modules/serviceCenter/services/serviceAgent/coreTools/_workspaceTools.py b/modules/serviceCenter/services/serviceAgent/coreTools/_workspaceTools.py index 98ee94b9..39a246ce 100644 --- a/modules/serviceCenter/services/serviceAgent/coreTools/_workspaceTools.py +++ b/modules/serviceCenter/services/serviceAgent/coreTools/_workspaceTools.py @@ -670,7 +670,7 @@ def _registerWorkspaceTools(registry: ToolRegistry, services): from modules.interfaces.interfaceVoiceObjects import getVoiceInterface mandateId = context.get("mandateId", "") voiceInterface = getVoiceInterface(currentUser=None, mandateId=mandateId) - sourceLanguage = args.get("sourceLanguage", "auto") + sourceLanguage = args.get("sourceLanguage") or None result = await voiceInterface.translateText(text, sourceLanguage=sourceLanguage, targetLanguage=targetLanguage) if result and result.get("success"): translated = result.get("translated_text", "") @@ -735,7 +735,7 @@ def _registerWorkspaceTools(registry: ToolRegistry, services): "properties": { "text": {"type": "string", "description": "Text to translate"}, "targetLanguage": {"type": "string", "description": "Target language ISO code (e.g. 'en', 'de', 'fr')"}, - "sourceLanguage": {"type": "string", "description": "Source language ISO code (default: auto-detect)"}, + "sourceLanguage": {"type": "string", "description": "Source language ISO code (e.g. 'de', 'en'). Omit or leave empty for auto-detection."}, }, "required": ["text", "targetLanguage"] },