-
-
Notifications
You must be signed in to change notification settings - Fork 0
Internationalisation
The operator/management SPA supports English, German, French, Spanish, and Chinese. English is the source language and the inline fallback; backend output, server logs, and the login screen stay English regardless of the user's choice.
A user's preferred language is stored on their IAM account (AppUser.language, default en) so
it follows them across devices. The browser caches it in localStorage (owcs.lang) for an
instant first paint before the server round-trip completes.
A language picker lives in the top bar next to the warehouse switcher. Each option is labelled in its own script (Deutsch, Français, Español, 中文) so a user who cannot read the current language can still find theirs. Selecting a language:
- Updates the
<html lang>attribute immediately. - Writes the choice to
localStorage(cache for next load). - Persists it to the IAM account via
PUT /api/iam/me/language(best-effort; a network failure still changes the language for the current session).
Both endpoints are resolved from the X-Auth-User header forwarded by the gateway.
| Method | Path | Description |
|---|---|---|
GET |
/api/iam/me/language |
Returns { "language": "en" } for the signed-in user. Falls back to en when the user has no row. |
PUT |
/api/iam/me/language |
Body { "language": "de" }. Unknown codes are coerced to en. Auto-provisions the AppUser row if the user has never been managed in IAM, so the preference still sticks. |
Supported codes: en · de · fr · es · zh.
The i18n layer is dependency-free (no i18n library):
| File | Role |
|---|---|
config.ts |
Lang union type, LANGS array, DEFAULT_LANG = 'en', LANG_STORAGE_KEY. |
LanguageContext.tsx |
React context + LanguageProvider. Reads the server preference once on mount; exposes lang + setLang. |
useT.ts |
useT(ns) hook — returns t(key, english). When lang === 'en' or the key is absent, the inline English is returned verbatim (no raw key ever leaks). |
dictionaries.ts |
Auto-discovers every locales/<lang>/<namespace>.ts via import.meta.glob. No central registry — parallel namespace work is conflict-free. |
LanguageSwitcher.tsx |
Top-bar <Select> wired to LanguageContext. |
locales/<lang>/<namespace>.ts |
One default-export { key: 'translated text' } object per language × namespace. English needs no files. |
-
Import and call
useTwith a namespace (one per screen / feature area):import { useT } from '../i18n/useT' const t = useT('inbound') return <h1>{t('title', 'Inbound orders')}</h1>
The second argument is the English source text and the fallback — wrapping a string with
t(...)never changes the English UI. Missing translations degrade to English, not a raw key. -
Add locale files for each of
de,fr,es,zh:// src/i18n/locales/de/inbound.ts export default { title: 'Wareneingangsaufträge', }
dictionaries.tspicks up the file automatically — no registry edit needed.
Do not wrap: data values, codes (SKU/HU/location codes), log text, or anything the backend owns. Keep numbers, units, and identifiers out of translated strings; interpolate them in the component.
- Backend output and API responses.
- Server logs (all Java / Go services).
- The Keycloak login screen (rendered outside the
LanguageProvider). - Error codes and identifiers shown in the UI (HU codes, location codes, SKU codes, etc.).
openWCS — open-source Warehouse Control System · summarized from build.md & docs/AS-BUILT.md (the repo docs are authoritative).
Design
Flows
- Areas
- Inbound and Inventory
- Slotting and Replenishment
- Goods-to-Person Stations
- Outbound Flow
- Equipment Integration
- Transport Overview
- Process Designer
- Mobile Process Designer
- Hardware Visualisation
- Host Integration
Reporting & Dashboards
Operations