fix: use Google Cloud API key for classic mode + translation verification
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2s
Two critical fixes: 1. Provider "google" (default classic mode) now checks for a Google Cloud API key (GOOGLE_CLOUD_API_KEY in env or admin settings). If present, uses GoogleCloudTranslationProvider (official API). Previously it always fell through to deep_translator (free scraper) which gets blocked in production, silently returning untranslated text. 2. Added translation verification: each translator now tracks how many texts were attempted vs actually changed. If 0 texts were translated, the job is marked as FAILED with a clear error message instead of returning the original file as "completed". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -951,7 +951,21 @@ async def _run_translation_job(
|
||||
translation_provider = None
|
||||
_p = provider.lower()
|
||||
|
||||
if _p in ("openrouter", "llm") and api_key:
|
||||
# "google" (default classic mode): use Google Cloud API key if available,
|
||||
# otherwise fall back to deep_translator (legacy, no key).
|
||||
if _p == "google":
|
||||
gc_key = _cfg(
|
||||
getattr(_admin_cfg.google_cloud, "api_key", None),
|
||||
"GOOGLE_CLOUD_API_KEY",
|
||||
)
|
||||
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)
|
||||
else:
|
||||
logger.info("google_provider_no_cloud_key_using_legacy", job_id=job_id)
|
||||
|
||||
elif _p in ("openrouter", "llm") and api_key:
|
||||
translation_provider = OpenRouterTranslationProvider(
|
||||
api_key, model, full_prompt
|
||||
)
|
||||
@@ -1114,6 +1128,30 @@ async def _run_translation_job(
|
||||
else:
|
||||
raise ValueError(f"Unsupported file type: {file_extension}")
|
||||
|
||||
# ── Verify translation actually produced results ──
|
||||
if not output_path.exists() or output_path.stat().st_size == 0:
|
||||
error_msg = "Translation failed: output file is empty or missing. The translation provider may be unavailable."
|
||||
logger.error(f"Job {job_id}: {error_msg}")
|
||||
tracker.set_error(error_msg)
|
||||
return
|
||||
|
||||
stats = job_translator.get_translation_stats()
|
||||
attempted = stats.get("attempted", 0)
|
||||
changed = stats.get("changed", 0)
|
||||
|
||||
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:
|
||||
error_msg = (
|
||||
f"Translation failed: 0 out of {attempted} texts were translated. "
|
||||
f"The provider ({provider}) may be unavailable or misconfigured. "
|
||||
f"Check your API keys in admin settings."
|
||||
)
|
||||
logger.error(f"Job {job_id}: {error_msg}")
|
||||
tracker.set_error(error_msg)
|
||||
return
|
||||
|
||||
if user_id:
|
||||
await tier_quota_service.increment_on_success(user_id)
|
||||
# Persist monthly usage counters in PostgreSQL (docs + pages)
|
||||
|
||||
Reference in New Issue
Block a user