Both error-mapping blocks (Gemini + OpenAI) are the same five patterns repeated with provider-specific text spliced in:
| Template key |
Triggers (substrings) |
Placeholders |
provider_rate_limit |
quota, rate, insufficient_quota, billing |
{provider_label}, {error} |
provider_invalid_key |
invalid + key, invalid_api_key |
{provider_label}, {error} |
provider_access_denied |
permission, access |
{provider_label}, {model}, {error} |
provider_safety_block |
safety, blocked, content_policy |
{provider_label}, {error} |
provider_model_not_found |
not found, 404 |
{provider_label}, {model}, {help_url}, {error} |
Suggested shape - anchors on the existing get_os_language() setting in app/config.py:341, which currently isn't wired to anything:
app/i18n/errors.en.json - flat catalog of templates with {placeholder} substitution
app/i18n/errors.<lang>.json - locale overrides; missing keys fall back to en
app/i18n/__init__.py exposing two helpers:
t(key, **kwargs) -> str - formatted lookup with locale + en fallback
classify_provider_error(exc, *, provider, model) -> str - does the substring matching against a triggers table in the catalog and returns the formatted message in one call
The error block in this PR collapses to roughly:
except Exception as e:
return {
"status": "error",
...,
"message": classify_provider_error(e, provider=provider, model=model_id),
}
Benefits:
- one mapping table instead of two near-identical blocks per provider
- localization-ready without touching call sites
- adding a new provider = adding a row to the catalog, not another
if/elif ladder
- avoids writing a bespoke message for every case - templates cover ~90% of them
- i think with the help of claude we can implement this pretty quick and easy
Both error-mapping blocks (Gemini + OpenAI) are the same five patterns repeated with provider-specific text spliced in:
provider_rate_limitquota,rate,insufficient_quota,billing{provider_label},{error}provider_invalid_keyinvalid+key,invalid_api_key{provider_label},{error}provider_access_deniedpermission,access{provider_label},{model},{error}provider_safety_blocksafety,blocked,content_policy{provider_label},{error}provider_model_not_foundnot found,404{provider_label},{model},{help_url},{error}Suggested shape - anchors on the existing
get_os_language()setting inapp/config.py:341, which currently isn't wired to anything:app/i18n/errors.en.json- flat catalog of templates with{placeholder}substitutionapp/i18n/errors.<lang>.json- locale overrides; missing keys fall back toenapp/i18n/__init__.pyexposing two helpers:t(key, **kwargs) -> str- formatted lookup with locale + en fallbackclassify_provider_error(exc, *, provider, model) -> str- does the substring matching against a triggers table in the catalog and returns the formatted message in one callThe error block in this PR collapses to roughly:
Benefits:
if/elifladder