@@ -62,6 +62,17 @@ def __init__(self, provider_name=None):
6262 CONFIDENCE_THRESHOLD = 0.80
6363
6464
65+ def _normalize_confidence (conf : Any ) -> float :
66+ """Normalize confidence value to float in [0.0, 1.0] range."""
67+ try :
68+ conf = float (conf )
69+ except (TypeError , ValueError ):
70+ return 0.0
71+ if math .isnan (conf ):
72+ return 0.0
73+ return max (0.0 , min (1.0 , conf ))
74+
75+
6576@dataclass
6677class TranslationContext : # pylint: disable=too-many-instance-attributes
6778 """A context object to hold data for a single translation operation."""
@@ -215,13 +226,7 @@ async def _detect_language_with_fallback(provider: TranslationProvider, text: st
215226
216227 lang_code , conf = detection
217228 detected_language = _normalize_lang_code (lang_code )
218- try :
219- conf = float (conf )
220- except (TypeError , ValueError ):
221- conf = 0.0
222- if math .isnan (conf ):
223- conf = 0.0
224- conf = max (0.0 , min (1.0 , conf ))
229+ conf = _normalize_confidence (conf )
225230 return detected_language , conf
226231
227232def _decide_if_translation_is_required (ctx : TranslationContext ) -> None :
@@ -516,11 +521,15 @@ async def detect_language(self, text: str) -> Optional[Tuple[str, float]]:
516521 """
517522 try :
518523 detection = await asyncio .to_thread (self ._translator .detect , text )
519- conf = float (detection .confidence ) if detection .confidence is not None else 0.0
520- return detection .lang , conf
521524 except Exception :
522525 logger .exception ("Google Translate language detection failed." )
523526 return None
527+ else :
528+ try :
529+ conf = _normalize_confidence (detection .confidence or 0.0 )
530+ except AttributeError :
531+ conf = 0.0
532+ return detection .lang , conf
524533
525534 async def translate (self , text : str , target_language : str ) -> Optional [Tuple [str , float ]]:
526535 """
@@ -535,10 +544,11 @@ async def translate(self, text: str, target_language: str) -> Optional[Tuple[str
535544 """
536545 try :
537546 translation = await asyncio .to_thread (self ._translator .translate , text , dest = target_language )
538- return translation .text , 1.0
539547 except Exception :
540548 logger .exception ("Google Translate translation failed." )
541549 return None
550+ else :
551+ return translation .text , 1.0
542552
543553
544554class AzureTranslateProvider :
@@ -609,14 +619,23 @@ async def translate(self, text: str, target_language: str) -> Optional[Tuple[str
609619 """
610620 try :
611621 try :
622+ # Try modern SDK signature first
612623 response = await asyncio .to_thread (
613624 self ._client .translate ,
614625 content = [text ],
615626 to = [target_language ],
616627 )
617628 except TypeError :
618- # Fallback for SDKs using positional body / 'to_language'
619- response = await asyncio .to_thread (self ._client .translate , [text ], to_language = [target_language ])
629+ # Try positional arguments
630+ try :
631+ response = await asyncio .to_thread (self ._client .translate , [text ], to_language = [target_language ])
632+ except TypeError :
633+ # Final fallback for different parameter names
634+ response = await asyncio .to_thread (
635+ self ._client .translate ,
636+ body = [text ],
637+ to_language = [target_language ]
638+ )
620639 if response and response [0 ].translations :
621640 return response [0 ].translations [0 ].text , 1.0
622641 except Exception :
@@ -644,18 +663,37 @@ async def translate_content(*chunks: Any, **kwargs) -> Any:
644663 Returns:
645664 The processed chunk(s), which may have its text translated and metadata updated.
646665 """
647- # Normalize inputs and remember original shape
648- input_was_list = len (chunks ) == 1 and isinstance (chunks [0 ], list )
649- batch = chunks [0 ] if input_was_list else list (chunks )
666+ # Always work with a list internally for consistency
667+ if len (chunks ) == 1 and isinstance (chunks [0 ], list ):
668+ # Single list argument: translate_content([chunk1, chunk2, ...])
669+ batch = chunks [0 ]
670+ return_single = False
671+ elif len (chunks ) == 1 :
672+ # Single chunk argument: translate_content(chunk)
673+ batch = list (chunks )
674+ return_single = True
675+ else :
676+ # Multiple chunk arguments: translate_content(chunk1, chunk2, ...)
677+ batch = list (chunks )
678+ return_single = False
650679
651680 results = []
652681
653682 for chunk in batch :
654683 target_language = kwargs .get ("target_language" , TARGET_LANGUAGE )
655684 translation_provider_name = kwargs .get ("translation_provider" , "noop" )
656685 fallback_providers = [
657- p .strip ().lower () for p in kwargs .get ("fallback_providers" , []) if isinstance (p , str ) and p .strip ()
686+ p .strip ().lower () for p in kwargs .get ("fallback_providers" , [])
687+ if isinstance (p , str ) and p .strip () and p .strip ().lower () in _provider_registry
688+ ]
689+
690+ invalid_providers = [
691+ p for p in kwargs .get ("fallback_providers" , [])
692+ if isinstance (p , str ) and p .strip () and p .strip ().lower () not in _provider_registry
658693 ]
694+ if invalid_providers :
695+ logger .warning ("Ignoring unknown fallback providers: %s" , invalid_providers )
696+
659697 confidence_threshold = kwargs .get ("confidence_threshold" , CONFIDENCE_THRESHOLD )
660698
661699 try :
@@ -703,7 +741,7 @@ async def translate_content(*chunks: Any, **kwargs) -> Any:
703741
704742 results .append (ctx .chunk )
705743
706- return results if ( input_was_list or len ( chunks ) != 1 ) else results [ 0 ]
744+ return results [ 0 ] if return_single else results
707745
708746
709747# Initialize providers
0 commit comments