Skip to content

feat(i18n) Internationalize hardcoded status messages in run_agent.py - #21639

Closed
loongfay wants to merge 1 commit into
NousResearch:mainfrom
YuanbaoTeam:dev
Closed

feat(i18n) Internationalize hardcoded status messages in run_agent.py#21639
loongfay wants to merge 1 commit into
NousResearch:mainfrom
YuanbaoTeam:dev

Conversation

@loongfay

@loongfay loongfay commented May 8, 2026

Copy link
Copy Markdown
Contributor

🌐 Internationalize hardcoded status messages in run_agent.py

Summary

All _emit_status() calls in run_agent.py previously used hardcoded English strings for runtime status messages (e.g. connection drops, retries, fallback switches). This made the agent output English-only even when the user's locale was set to another language like Chinese.

Changes

  • Added from agent.i18n import t import to run_agent.py
  • Replaced ~30 hardcoded English _emit_status(...) calls with t("status.xxx", ...) using the project's existing i18n framework
  • Added 32 new translation keys under the status: section in all 8 locale files (locales/{en,zh,ja,de,es,fr,tr,uk}.yaml)

Translation keys added

no_response_streaming, no_response_nonstreaming, connection_dropped_toolcall, connection_dropped, reconnected, connection_failed, switching_fallback, stale_connections_cleaned, preflight_compression, context_reduced, rate_limited_fallback, empty_response_fallback, max_retries_fallback, max_retries_failed, payload_too_large, context_too_large, compressed_retrying, non_retryable_error_fallback, non_retryable_error, max_retries_exhausted_fallback, rate_limited_final, api_failed_final, rate_limited_waiting, retrying, guardrail_halted, stream_interrupted_using_content, empty_after_tools_using_prior, empty_after_tools_nudging, thinking_only_prefilling, empty_response_retrying, empty_response_switching_fallback, switched_to_fallback

Example

# Before:
self._emit_status(f"⚠️ No response from provider for {int(_stale_elapsed)}s (model: {api_kwargs.get('model', 'unknown')}, context: ~{_est_ctx:,} tokens). Reconnecting...")

# After:
self._emit_status(t("status.no_response_streaming", elapsed=int(_stale_elapsed), model=api_kwargs.get("model", "unknown"), context=f"{_est_ctx:,}"))

Files modified

  • run_agent.py
  • locales/en.yaml
  • locales/zh.yaml
  • locales/ja.yaml
  • locales/de.yaml
  • locales/es.yaml
  • locales/fr.yaml
  • locales/tr.yaml
  • locales/uk.yaml

Verification

  • run_agent.py passes ast.parse syntax check
  • ✅ All 8 YAML files parse correctly
  • ✅ All locale files have identical key sets (50 keys each, 32 new)

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint labels May 8, 2026
@loongfay

loongfay commented May 9, 2026

Copy link
Copy Markdown
Contributor Author

waiting

@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Thanks for the careful work on this — the implementation is clean (32 keys × 8 locales kept in sync, all _emit_status sites threaded consistently through t()), and the verification was thorough.

Closing as out of scope, though — not because the change is wrong but because Hermes' i18n layer is intentionally a thin slice. The current scope policy is documented in agent/i18n.py:

"Scope (thin slice, by design): only the highest-impact static strings shown to the user by Hermes itself — approval prompts, a handful of gateway slash command replies, restart-drain notices. Agent-generated output, log lines, error tracebacks, tool outputs, and slash-command descriptions all stay in English."

And Teknium's foundation PR #20231 (which set the i18n layer up) is explicit about why run_agent.py runtime telemetry is excluded:

NOT translated (stays English):

  • Agent responses (controlled by the model + user prompt, not this layer)
  • Log lines, error tracebacks, debug output

"Full i18n across cli.py / gateway/run.py / hermes_cli/setup.py would mean extracting hundreds of English literals and paying a forever-tax to keep new PRs wrapping strings in t(...). Scope was reviewed before building — thin slice covers the highest-impact visible messages without the drift tax."

The _emit_status calls this PR wraps are exactly that category — runtime lifecycle messages (connection drops, retries, fallback switches, rate-limit waits) where the substantive content (model names, byte counts, exception strings) is interpolated and would still render in English after translation. So the strings remain mixed-language even with the i18n layer applied, and every new _emit_status site added in the future would need to remember to wrap + sync 8 locale files. That's the drift tax Teknium decided against paying.

If you'd like agent telemetry in another language end-to-end, the supported path is to ask the agent to respond in your language in your prompt — the model controls the response language directly, which is more natural than catalogging every internal status string.

Thanks again for the contribution and for the clean implementation work — closing as out of scope rather than as a quality issue.

@loongfay

loongfay commented May 9, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the careful work on this — the implementation is clean (32 keys × 8 locales kept in sync, all _emit_status sites threaded consistently through t()), and the verification was thorough.

Closing as out of scope, though — not because the change is wrong but because Hermes' i18n layer is intentionally a thin slice. The current scope policy is documented in agent/i18n.py:

"Scope (thin slice, by design): only the highest-impact static strings shown to the user by Hermes itself — approval prompts, a handful of gateway slash command replies, restart-drain notices. Agent-generated output, log lines, error tracebacks, tool outputs, and slash-command descriptions all stay in English."

And Teknium's foundation PR #20231 (which set the i18n layer up) is explicit about why run_agent.py runtime telemetry is excluded:

NOT translated (stays English):

  • Agent responses (controlled by the model + user prompt, not this layer)
  • Log lines, error tracebacks, debug output

"Full i18n across cli.py / gateway/run.py / hermes_cli/setup.py would mean extracting hundreds of English literals and paying a forever-tax to keep new PRs wrapping strings in t(...). Scope was reviewed before building — thin slice covers the highest-impact visible messages without the drift tax."

The _emit_status calls this PR wraps are exactly that category — runtime lifecycle messages (connection drops, retries, fallback switches, rate-limit waits) where the substantive content (model names, byte counts, exception strings) is interpolated and would still render in English after translation. So the strings remain mixed-language even with the i18n layer applied, and every new _emit_status site added in the future would need to remember to wrap + sync 8 locale files. That's the drift tax Teknium decided against paying.

If you'd like agent telemetry in another language end-to-end, the supported path is to ask the agent to respond in your language in your prompt — the model controls the response language directly, which is more natural than catalogging every internal status string.

Thanks again for the contribution and for the clean implementation work — closing as out of scope rather than as a quality issue.

okay, got it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants