mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-10-22 08:25:21 +08:00
feat(i18n): localize backend messages by workspace language
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
# 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`.
|
||||
Reference in New Issue
Block a user