3.6 KiB
Backend message language
Workspace settings expose one Workspace language, independent of each member's
WebUI language. It selects LangBot-owned API business errors, model error prefixes,
Pipeline default notices and international platform replies. Supported locales are
en_US, zh_Hans, zh_Hant, ja_JP, es_ES, ru_RU, th_TH and vi_VN.
Workspaces without a setting default to English. Existing custom messages and
historical records are not rewritten.
Storage and boundaries
pkg/i18n/workspace.py stores message_language in existing WorkspaceMetadata;
no database migration or instance-wide configuration is needed. Reads and writes
use tenant-scoped units of work. GET/PUT /api/v1/workspaces/current/language
require workspace.view / workspace.update; matching MCP tools are
get_workspace_message_language and set_workspace_message_language.
An authenticated Workspace takes precedence over the browser's
X-LangBot-Language header. The header supplies presentation language only for
account-only or unauthenticated responses and never selects a tenant. HTTP, MCP,
Pipeline and adapter boundaries set a ContextVar so concurrent Workspaces do not
share a language. Adapter SDK thread callbacks use their owning bot's cached
Workspace language, never the calling request's language.
The per-application cache holds at most 256 Workspaces for 30 seconds. Local writes update the cache immediately; other processes refresh at the next async message/request boundary after expiry. A running operation keeps its selected language. Synchronous SDK callbacks use the most recently loaded value.
Pipeline overrides
The output misc section accepts these optional string settings:
| Setting | Default purpose | Placeholder |
|---|---|---|
failure-hint |
Request/runner execution failure | none |
rate-limit-hint |
Rate limit reached | none |
content-filter-hint |
Message rejected by content filter | none |
content-filter-error-hint |
Content check failed | none |
tool-call-hint |
Tool call notification | {tools} |
runner-not-found-hint |
Configured runner missing | {runner} |
runner-not-authorized-hint |
Runner authorization failure | none |
runner-unavailable-hint |
Runner temporarily unavailable | none |
Blank values inherit the Workspace translation. Custom text is emitted literally
with only the documented placeholder replaced. The previous shipped
failure-hint value Request failed. also inherits language; this avoids a data
migration. Existing output switches (including tool-call visibility and exception
handling) retain their behavior.
Adding messages
Use pkg.i18n.t() with a stable English template and named parameters. Add the
same key and placeholders to all eight JSON catalogs. The catalog parity test
checks completeness and formatting. pipeline_notice() handles configurable
notices. Exact aliases at the API response boundary cover legacy business wording;
do not add substring replacement of arbitrary error text.
China-only adapters, field validation diagnostics, raw provider/plugin errors, tracebacks, protocol values and machine-readable status codes are outside this translation layer. Their values remain useful for diagnostics and interoperability. Model errors translate LangBot's category/prefix while retaining upstream detail. Plugin-authored content must use the plugin's own localization. System prompts and user-authored content are not translated.
Locale JSON files are included in Python package data. Focused coverage lives in
tests/unit_tests/test_backend_i18n.py, the Workspace HTTP integration tests and
web/tests/e2e/workspace-language.spec.ts.