Problem or Motivation
OpenCloudTouch is used internationally — the SoundTouch platform had a global user base, and the community around it spans multiple countries. Currently, the entire UI is English-only. German-speaking users (a significant portion of the community, as seen in discussions and issues) have no native-language experience.
There is no mechanism to:
- Display UI labels, messages, and explanations in the user's preferred language
- Allow community members to contribute translations
- Switch the language without technical knowledge
This creates an unnecessary barrier for non-English speakers, especially for setup, error messages, and device configuration flows.
Desired Behaviour
1. Language Selector in the UI
Add a language selector dropdown in the top navigation bar (or Settings page header) that allows users to switch between supported languages at runtime.
Design requirements:
- Small flag icon + language name in the native language (e.g. Deutsch, English)
- Dropdown placement: top-right nav bar, next to theme toggle, or in Settings General
- Selected language persists in localStorage across sessions
- Falls back to browser navigator.language on first visit (auto-detect)
- Instant switch without page reload
Initially supported languages:
| Code |
Native name |
| en |
English |
| de |
Deutsch |
2. All UI text must be externalized
Every user-visible string must be moved to translation files:
- Page titles and headings
- Button labels (Discover, Add Device, Save, Cancel, ...)
- Form labels and placeholders
- Status messages and notifications (toast messages)
- Error messages (connection errors, validation errors)
- Empty state messages
- Confirmation dialogs
- Settings labels and descriptions
- Device card labels (Volume, Now Playing, Presets, ...)
- Navigation items
3. Translation file format
Use JSON translation files structured by namespace, placed in apps/frontend/src/i18n/locales/:
apps/frontend/src/i18n/
locales/
en.json <- source of truth (English)
de.json <- German translation
index.ts <- i18n init and export
Example en.json:
{
"common": {
"save": "Save",
"cancel": "Cancel",
"loading": "Loading...",
"error": "An error occurred"
},
"devices": {
"discover": "Discover Devices",
"noDevices": "No devices found. Start discovery or add a device manually.",
"volume": "Volume",
"nowPlaying": "Now Playing"
},
"settings": {
"title": "Settings",
"manualIps": {
"label": "Manual Device IPs",
"placeholder": "192.168.1.100",
"add": "Add IP"
}
},
"errors": {
"connectionFailed": "Could not connect to the device.",
"discoveryFailed": "Discovery failed. Check your network settings."
}
}
4. Recommended i18n library: react-i18next
Industry standard for React:
- Hooks-based: const { t } = useTranslation()
- Lazy loading of locale files supported
- Pluralization, interpolation, and formatting built-in
- MIT license, actively maintained
// Before
<button>Discover Devices</button>
// After
const { t } = useTranslation();
<button>{t('devices.discover')}</button>
5. Translation Contributing Template
A dedicated GitHub Issue template translation_contribution.yml should be added to .github/ISSUE_TEMPLATE/ to allow community members to contribute translations for new languages.
The template lists all translatable strings in English (source of truth from en.json) as a checklist. Contributors:
- Open an issue using the template
- Select the target language
- Provide translations inline in the issue
- A maintainer creates the locale JSON file and merges it
This lowers the contribution barrier — no fork/PR knowledge required for non-technical translators.
Acceptance Criteria
Alternatives Considered
- Separate URL per language (e.g. /de/) — too complex for a single-user household app; localStorage is sufficient
- Auto-translate via browser — uncontrolled, inconsistent results; no fallback for OCT-specific terminology
- Hardcode a second language in components — does not scale, creates maintenance nightmare
Additional Context
- Initial scope: EN + DE only. Additional languages via community contribution (translation_contribution issue template).
- Backend API responses (device names, preset titles) come from the SoundTouch device itself — no translation needed.
- Error messages from backend (detail field) can be translated on the frontend using error codes — follow-up.
- Estimated effort: M (medium) — mostly mechanical string extraction + library setup.
Affected Area
Frontend / UI
Problem or Motivation
OpenCloudTouch is used internationally — the SoundTouch platform had a global user base, and the community around it spans multiple countries. Currently, the entire UI is English-only. German-speaking users (a significant portion of the community, as seen in discussions and issues) have no native-language experience.
There is no mechanism to:
This creates an unnecessary barrier for non-English speakers, especially for setup, error messages, and device configuration flows.
Desired Behaviour
1. Language Selector in the UI
Add a language selector dropdown in the top navigation bar (or Settings page header) that allows users to switch between supported languages at runtime.
Design requirements:
Initially supported languages:
2. All UI text must be externalized
Every user-visible string must be moved to translation files:
3. Translation file format
Use JSON translation files structured by namespace, placed in apps/frontend/src/i18n/locales/:
Example en.json:
{ "common": { "save": "Save", "cancel": "Cancel", "loading": "Loading...", "error": "An error occurred" }, "devices": { "discover": "Discover Devices", "noDevices": "No devices found. Start discovery or add a device manually.", "volume": "Volume", "nowPlaying": "Now Playing" }, "settings": { "title": "Settings", "manualIps": { "label": "Manual Device IPs", "placeholder": "192.168.1.100", "add": "Add IP" } }, "errors": { "connectionFailed": "Could not connect to the device.", "discoveryFailed": "Discovery failed. Check your network settings." } }4. Recommended i18n library: react-i18next
Industry standard for React:
5. Translation Contributing Template
A dedicated GitHub Issue template translation_contribution.yml should be added to .github/ISSUE_TEMPLATE/ to allow community members to contribute translations for new languages.
The template lists all translatable strings in English (source of truth from en.json) as a checklist. Contributors:
This lowers the contribution barrier — no fork/PR knowledge required for non-technical translators.
Acceptance Criteria
Alternatives Considered
Additional Context
Affected Area
Frontend / UI