Skip to content

feat: internationalization (i18n) system — EN, RU, ES#134

Open
flathead wants to merge 9 commits intoAxenide:devfrom
flathead:feature/i18n
Open

feat: internationalization (i18n) system — EN, RU, ES#134
flathead wants to merge 9 commits intoAxenide:devfrom
flathead:feature/i18n

Conversation

@flathead
Copy link
Copy Markdown

@flathead flathead commented Mar 27, 2026

What this does

Adds a runtime i18n system to Ambxst and migrates all hardcoded UI strings to use it. Three languages included: English, Russian, Spanish.

Translation quality

Russian and Spanish were translated mostly with machine translators and AI tools, then manually spot-checked. Quality may be uneven - wrong grammatical forms, unnatural phrasing, context mismatches are possible. Native speaker corrections are welcome.

How to add a new language

  1. Copy translations/en.json to translations/{lang}.json (use standard locale codes: fr, de, ja, etc.)
  2. Translate all values - do not change the keys
  3. Add an entry to translations/languages.json:
{ "code": "fr", "name": "Français", "direction": "ltr" }
  1. The language will be auto-detected from system locale, or users can set it manually via Config.system.language = "fr" in their config

How to fix or improve existing translations

Just edit the relevant translations/{lang}.json file. Keys are sorted alphabetically. Each key maps directly to a UI string - the key name usually makes the context clear (e.g. "wallpapers.oled", "settings.theme.colors").

Architecture

modules/services/I18n.qml - new singleton that loads the JSON file and exposes I18n.t("key"). Detects locale via Qt.locale(), falls back to "en".

.pragma library workaround - JS files with .pragma library cannot access QML singletons, so notification_utils.js and notes_utils.js receive the t function as a parameter from their callers.

Bug fixes included

  • ToolsMenu.qml: i18n() calls (undefined function) were crashing the OCR panel - replaced with I18n.t()
  • WallpapersTab.qml: Tint label was showing "OLED" due to wrong key
  • CompositorPanel, ThemePanel, SystemPanel: subsection titles are now translated dynamically
  • SchemeSelector.qml: was using I18n.t() without the required import

Files

72 files changed. New files: modules/services/I18n.qml, translations/en.json, translations/ru.json, translations/es.json, translations/languages.json.

Screenshots (idk what for 😄)

1

@flathead
Copy link
Copy Markdown
Author

Merge order for related PRs

This repo currently has 4 open PRs from this fork. They touch some of the same files, so merging them in the right order avoids most conflicts:

  1. feat: add volume scroll to controls button and players #132 (volume scroll) - no conflicts with anything, merge first
  2. feat: add keyboard layout indicator to bar #130 (keyboard layout indicator) - no conflicts with feat: add volume scroll to controls button and players #132
  3. feat: add audio device switcher to bar #131 (audio device switcher) - no conflicts with feat: add keyboard layout indicator to bar #130
  4. feat: internationalization (i18n) system — EN, RU, ES #134 (i18n, this PR) - conflicts with feat: add keyboard layout indicator to bar #130 and feat: add audio device switcher to bar #131 in a few files

If you merge #134 last, the only conflicts will be in:

All conflicts are straightforward - no logic changes, just placement of new blocks alongside each other.

Introduces a full i18n infrastructure and migrates all hardcoded UI
strings across the codebase to use the new translation system.

## New files
- modules/services/I18n.qml — singleton service that loads JSON
  translation files at runtime based on system locale or config
- translations/en.json — English (base, ~637 keys)
- translations/ru.json — Russian translation
- translations/es.json — Spanish translation
- translations/languages.json — language metadata registry

## Infrastructure
- I18n.qml detects locale via Qt.locale(), falls back to "en"
- Config.qml: added `language` property (default "auto") for manual
  language override; added `rus` bool to OCR config
- config/defaults/system.js: added language and rus defaults
- .pragma library JS files (notification_utils.js, notes_utils.js)
  receive `t` as a parameter from callers since they cannot access
  QML singletons directly

## String migration
All hardcoded UI strings across 67 files replaced with I18n.t("key"):
- Bar: battery, layout selector, controls button, tools button
- Clock: month/day names (fixes Qt.locale() genitive case in RU),
  weather day labels, pomodoro controls
- Dashboard controls: all settings panels (Compositor, Theme, Shell,
  System, Binds, Color Picker, Wallpapers, Audio, Bluetooth, WiFi,
  EasyEffects, Gradient editor, Variant editor)
- Dashboard widgets: calendar, clipboard (relative timestamps),
  notes (relative timestamps), notifications, launcher, overview,
  tmux, emoji, metrics, full/compact player, quick controls,
  presets, power menu
- Tools: screenshot overlay/tool, screen recorder
- Sidebar: AI assistant slash command descriptions
- Dock, Desktop, CodeBlock, ModelSelectorPopup

## Bug fixes included
- ToolsMenu.qml: fixed `i18n()` calls (undefined function) that
  caused OCR panel crash — replaced with `I18n.t()`
- WallpapersTab.qml: fixed Tint label showing "OLED" (key mismatch)
- CompositorPanel, ThemePanel, SystemPanel: subsection titles now
  translated dynamically (was using raw capitalize() fallback)
- SchemeSelector.qml: added missing `import qs.modules.services`

## Translation notes
- Russian: uses nominative month names (not genitive from Qt.locale())
- All 637 keys verified present in all three locale files
- Dynamic key patterns (e.g. settings.shell.{sectionId}) verified
OSD.qml: fix i18n.t() -> I18n.t() (lowercase caused empty strings)

Ai.qml: migrate hardcoded user-visible strings to I18n.t():
- /model command: model not found, switched to model messages
- /help command: full help message
- API key missing error (with model name and key_id substitution)
- Network request failed error
- No response from API message
- Command executed successfully (no output) message
- Model descriptions for all 6 providers

translations: add 13 new keys to en/ru/es (ai.api_key_missing,
ai.cmd_no_output, ai.desc_*, ai.env_variable, ai.help_message,
ai.model_not_found, ai.network_failed, ai.no_response,
ai.switched_to_model)
flathead and others added 3 commits March 27, 2026 23:34
Adds keys for the new resource monitor settings screen:
enabled toggle, location (bar/dashboard), bar side,
visible items (CPU/RAM/GPU/disk), disk list title,
save/unsaved status, and bar tooltip.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Axenide
Copy link
Copy Markdown
Owner

Axenide commented Mar 28, 2026

Wow nice, I was gonna add this to 1.3.0 lol but if this works it would be great. I'll test when I have the time. :)

flathead added 4 commits April 1, 2026 21:48
Adds 39 keys under calendar.bar.*, calendar.event.*, calendar.form.*,
and calendar.settings.* namespaces for the calendar integration feature.
Covers bar indicator labels, event form fields, validation errors,
reminder options, and the barAlwaysShow setting toggle.
Add calendar.panel.* keys for all CalendarPanel UI strings (accounts,
settings, form fields, section headers, arrival settings) and missing
calendar.form.* keys (new_event, edit_event, time_placeholder) for
EventPopup. All three languages: en, ru, es. 37 new keys each.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants