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"]
},