fix: Google Cloud API translation key environment and fallback logic
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2s

This commit is contained in:
2026-05-17 16:13:05 +02:00
parent c0f93501cc
commit 087341b045
2 changed files with 59 additions and 3 deletions

View File

@@ -105,6 +105,7 @@ services:
- STRIPE_PRO_PRICE_ID=${STRIPE_PRO_PRICE_ID:-}
- STRIPE_BUSINESS_PRICE_ID=${STRIPE_BUSINESS_PRICE_ID:-}
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID:-}
- GOOGLE_CLOUD_API_KEY=${GOOGLE_CLOUD_API_KEY:-}
volumes:
- uploads_data:/app/uploads
- outputs_data:/app/outputs

View File

@@ -836,6 +836,47 @@ def _estimate_pages(file_path: Path, file_extension: str) -> int:
return 1
class _GoogleCloudWithFallback:
"""Tries Google Cloud API first, falls back to deep_translator on error.
This avoids a hard crash when the Cloud API key is invalid, quota is
exceeded, or the network is unreachable. The legacy GoogleTranslator
(deep_translator, free, no key) is used as a best-effort fallback.
"""
def __init__(self, cloud_adapter, legacy_provider):
self.cloud = cloud_adapter
self.legacy = legacy_provider
self.provider_name = "google_cloud_with_fallback"
def translate(self, text, target_language, source_language="auto"):
try:
return self.cloud.translate(text, target_language, source_language)
except Exception as e:
logger.warning(
"google_cloud_failed_fallback_to_legacy",
error=str(e)[:200],
)
return self.legacy.translate(text, target_language, source_language)
def translate_batch(
self, texts, target_language, source_language="auto", **kwargs
):
try:
return self.cloud.translate_batch(
texts, target_language, source_language
)
except Exception as e:
logger.warning(
"google_cloud_batch_failed_fallback_to_legacy",
error=str(e)[:200],
text_count=len(texts),
)
return self.legacy.translate_batch(
texts, target_language, source_language
)
async def _run_translation_job(
job_id: str,
input_path: Path,
@@ -953,6 +994,9 @@ async def _run_translation_job(
# "google" (default classic mode): use Google Cloud API key if available,
# otherwise fall back to deep_translator (legacy, no key).
# When the Cloud API key IS present, wrap it in a fallback so that
# quota / network errors don't kill the job — deep_translator is tried
# as a best-effort second chance.
if _p == "google":
gc_key = _cfg(
getattr(_admin_cfg.google_cloud, "api_key", None),
@@ -960,8 +1004,13 @@ async def _run_translation_job(
)
if gc_key:
from services.providers.google_cloud_provider import LegacyGoogleCloudAdapter
translation_provider = LegacyGoogleCloudAdapter(gc_key)
logger.info("google_provider_using_cloud_api", job_id=job_id)
from services.translation_service import GoogleTranslationProvider
cloud_adapter = LegacyGoogleCloudAdapter(gc_key)
legacy_fallback = GoogleTranslationProvider()
translation_provider = _GoogleCloudWithFallback(
cloud_adapter, legacy_fallback
)
logger.info("google_provider_using_cloud_api_with_fallback", job_id=job_id)
else:
logger.info("google_provider_no_cloud_key_using_legacy", job_id=job_id)
@@ -1142,7 +1191,7 @@ async def _run_translation_job(
if attempted > 0:
ratio = changed / attempted
logger.info(f"Job {job_id}: translation stats — {changed}/{attempted} texts changed ({ratio:.0%})")
if ratio < 0.15 and changed == 0:
if changed == 0:
error_msg = (
f"Translation failed: 0 out of {attempted} texts were translated. "
f"The provider ({provider}) may be unavailable or misconfigured. "
@@ -1151,6 +1200,12 @@ async def _run_translation_job(
logger.error(f"Job {job_id}: {error_msg}")
tracker.set_error(error_msg)
return
elif ratio < 0.05:
# Very suspicious — likely partial failure, warn but don't block
logger.warning(
f"Job {job_id}: suspiciously low translation rate: "
f"{changed}/{attempted} ({ratio:.1%})"
)
if user_id:
await tier_quota_service.increment_on_success(user_id)