DeepLX/translate
Vincent Yang 057387c957
feat(translate): validate source/target language codes (#218)
Previously TranslateByDeepLX silently mapped any caller-supplied code
through toOneshotLang(), falling back to a lowercased pass-through for
unknown codes. The oneshot endpoint accepts unknown codes with a 200
but echoes the source text back untranslated, leaving callers to
distinguish "translated, identical to source" from "language not
supported" without a clear signal.

Validate strictly against the language table the extension bundles in
background.js (array `y` for target-capable codes, `A` for the
source-only EN / PT aliases) and return HTTP 400 with a list of
supported codes on mismatch. This also catches:

  - target_lang = ""        → "target_lang is required"
  - target_lang = "auto"    → "target_lang cannot be \"auto\"; pick one of: ..."
  - source_lang = ""/"auto" → allowed, server autodetects
  - case-insensitive       → strings.ToUpper before lookup

Pick up languages the previous map missed:

  + ES-419 (Latin American Spanish)
  + HE     (Hebrew)
  + VI     (Vietnamese)

Fix the EN / PT source-lang mapping: the extension's `A` array maps
both to the generic langCodeForIta ("en"/"pt"), not the regional
default. As a target they continue to resolve to en-US / pt-BR for
backward compat with callers that historically passed "EN" / "PT".

Verified end-to-end:
  - 5 valid codes (DE, ZH-HANT, HE, VI, ES-419) → 200 + translated text
  - Invalid target "XX"  → 400, message lists 38 supported codes
  - Invalid source "ZZ"  → 400, message lists 38 codes + "auto"
  - target_lang "auto"   → 400
  - source autodetect (empty / "auto") + valid target → 200
  - Lowercase input "de" → 200 (case-insensitive)
2026-05-22 12:13:38 +08:00
..
translate.go feat(translate): validate source/target language codes (#218) 2026-05-22 12:13:38 +08:00
types.go feat(translate): migrate to oneshot endpoint (#217) 2026-05-22 12:04:44 +08:00