Skip to content

feat: i18n localization system + complete Russian translation#66

Open
Volfheim wants to merge 4 commits into
ilyamiro:masterfrom
Volfheim:feature/i18n-russian-localization
Open

feat: i18n localization system + complete Russian translation#66
Volfheim wants to merge 4 commits into
ilyamiro:masterfrom
Volfheim:feature/i18n-russian-localization

Conversation

@Volfheim

@Volfheim Volfheim commented May 5, 2026

Copy link
Copy Markdown

Summary

Adds a lightweight, non-breaking localization layer to Quickshell with a complete Russian translation (337 keys) as the first community-contributed language pack.

Closes #65


Architecture

  • Config.tr(key, fallback) — returns the translated string, or the original English fallback if the key is missing
  • i18n/*.json — external translation dictionaries. Community can add new languages (i18n/de.json, i18n/fr.json, etc.) without touching QML
  • uiLanguage — persisted in settings.json, live-reloaded via inotifywait (no shell restart needed)
  • Language selector added to Settings > General with pill-style toggle

What is covered (11 files changed, +626 / -95)

Module What is translated
Config.qml Translation engine (tr(), loadTranslations(), langUpdateTrigger)
TopBar.qml Date (with locale-aware day/month order), BT status, live language reload
Main.qml Live language reload via settings watcher
CalendarPopup.qml Day names, month names, weather descriptions, schedule labels
SettingsPopup.qml All labels, tab names, placeholders, instructions, temperature units
FocusTimePopup.qml Dates with proper grammatical cases, week ranges, day abbreviations
MonitorPopup.qml Apply / Apply All button
bt_fetch.sh BT toggle notifications
screenshot.sh Screenshot & recording notifications
i18n/en.json Empty — all English strings are inline fallbacks
i18n/ru.json 337 keys covering every UI string

Design decisions

  • Zero breakage — if uiLanguage is not set or en.json is empty, everything works exactly as before
  • Russian dates use proper genitive case (4 мая, not 4 Май) and Russian day/month order (DD Month vs Month DD)
  • Live switching — changing language in Settings instantly updates all widgets including TopBar (separate process)
  • Shell scripts read uiLanguage from settings.json via grep for notification translation, gracefully falling back to English

How to add a new language

  1. Create i18n/xx.json with the same keys as ru.json
  2. Add a button to the language selector in SettingsPopup.qml
  3. Done — no other files need changes

Testing

Tested on CachyOS (Arch) with Hyprland, Quickshell, Iosevka Nerd Font, ru_RU.UTF-8 locale.

Add a lightweight, non-breaking i18n layer to Quickshell with a complete
Russian translation as the first community-contributed language pack.

Architecture:
- Config.tr(key, fallback) helper returns translated string or English fallback
- i18n/*.json external translation dictionaries
- uiLanguage saved in settings.json, live-reloaded via inotifywait
- Language selector added to Settings > General

Changes (11 files):
- Config.qml: translation system (tr, loadTranslations, langUpdateTrigger)
- TopBar.qml: localized date, BT status, live language reload
- Main.qml: live language reload via settingsReader
- CalendarPopup.qml: localized days, months, weather descriptions
- SettingsPopup.qml: all labels, placeholders, instructions
- FocusTimePopup.qml: localized dates with proper grammatical cases
- MonitorPopup.qml: Apply/Apply All button text
- bt_fetch.sh: localized BT toggle notifications
- screenshot.sh: localized screenshot/recording notifications
- i18n/en.json: empty (all fallbacks are in QML code)
- i18n/ru.json: 337 translation keys covering all UI modules

Design decisions:
- Zero breakage: English fallback is always the original hardcoded string
- Community-driven: add i18n/xx.json without touching QML
- Survives updates: translation files are separate from QML code
- Russian dates use genitive case (4 мая, not 4 Май)
- Date order adapts per locale (DD Month vs Month DD)

Closes ilyamiro#65
@ilyamiro

ilyamiro commented May 5, 2026

Copy link
Copy Markdown
Owner

Did you write this with AI?

@ilyamiro

ilyamiro commented May 5, 2026

Copy link
Copy Markdown
Owner

It seems so. But sure, i think i will review and probably merge this.

@Volfheim

Volfheim commented May 5, 2026

Copy link
Copy Markdown
Author

Hi! Yes, I used an AI assistant to help with the boilerplate and the massive amount of translation keys (337 of them!) to ensure consistency and speed. However, I've manually verified and tested every single string and logic change on my local setup (CachyOS + Hyprland).

I'm the one who proposed this in #65, and I decided to implement it myself to make the i18n system as clean and non-breaking as possible. I've been using it for a while now, and live language switching works perfectly across all widgets. Looking forward to your review!

@Volfheim

Volfheim commented May 5, 2026

Copy link
Copy Markdown
Author

I used AI to help me translate the above message to make it look better, but as a native speaker, I can vouch for the quality of the meaning conveyed in my translation; I did a lot of work. 🙃

@ilyamiro

ilyamiro commented May 5, 2026

Copy link
Copy Markdown
Owner

I also speak Russian, so don't worry. but there are at least a few issues: 1. "settings.box.temp_desc": "Celsius / Fahrenheit / K", - translate this to Цельсий / Фаренгейт / Кельвин? seems logical. 2. the напр. shortenings or whatever else it has don't do, because f.x. works in english but in russian it would be better to say например fully.

@Volfheim

Volfheim commented May 5, 2026

Copy link
Copy Markdown
Author

I suspected that you speak Russian based on your nickname, Ilya. 😁 "Градусы они мои" That's why I wrote the temperature units in the plural, since the translation is for Russian speakers. Regarding the abbreviations, I tried not to change the appearance, so that's what I did. I'll correct the abbreviations now.

@ilyamiro

ilyamiro commented May 5, 2026

Copy link
Copy Markdown
Owner

Про цельсий и т.д я имею ввиду что они вообще не переведены. Они на английском так и были. Я не про склонение говорил

- settings.box.temp_desc: 'Celsius / Fahrenheit / K' → 'Цельсий / Фаренгейт / Кельвин'
- Replace all 'напр.' abbreviations with full 'например' for cleaner Russian UI
@Volfheim

Volfheim commented May 5, 2026

Copy link
Copy Markdown
Author

Fixed both issues:

  • settings.box.temp_desc: "Celsius / Fahrenheit / K" → "Цельсий / Фаренгейт / Кельвин"
  • All напр. abbreviations expanded to full например

Thanks for the review!

@Volfheim

Volfheim commented May 5, 2026

Copy link
Copy Markdown
Author

Неа, у меня там 2 разных ключа для этого, они переведены, чекни 299 строчку, просто UI её юзает, щас первый ключ тоже переведу1iuDYDA0m6d6EQQo0Clmfaw9FknkWxFeDskVpQRS2-Ta_0powQGJG74C5MKfpvqhCZ9_I2rW08lKr2SslJNdgmxA.jpg

@Volfheim

Volfheim commented May 5, 2026

Copy link
Copy Markdown
Author

И всё же вопрос множественное число оставить или единственное, попробовал оба варианта, в поиске по настройкам сейчас единственное число как ты и написал, а в ui множественное как я изначально сделал, и всё же склоняюсь к множественному, но в общем как скажешь 👍

@ilyamiro

ilyamiro commented May 5, 2026

Copy link
Copy Markdown
Owner

Ну просто это "Единицы измерения" и их не склонять лучше. Оставь в единственном

@Volfheim

Volfheim commented May 5, 2026

Copy link
Copy Markdown
Author

Сделано, заодно (не юзал поиск по настройкам особо) заметил недоперевод в плейсхолдере под поиском, его тоже в ключи добавил и перевёл

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a lightweight i18n layer to the Quickshell QML UI (with external JSON dictionaries) and ships a full Russian translation, plus localized notifications in a couple of helper scripts. The design keeps English as inline fallbacks to remain non-breaking when translations are missing.

Changes:

  • Introduces Config.tr() + translation loading (i18n/*.json) and persists uiLanguage in settings.json.
  • Replaces many hardcoded UI strings in QML with translation lookups and adds an in-UI language selector.
  • Localizes user-facing notifications in screenshot.sh and bt_fetch.sh based on uiLanguage.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
.config/hypr/scripts/quickshell/Config.qml Adds translation loader (loadTranslations), tr(), and persists uiLanguage; translates notify messages.
.config/hypr/scripts/quickshell/i18n/en.json Adds empty English dictionary (English remains inline fallbacks).
.config/hypr/scripts/quickshell/i18n/ru.json Adds Russian translation dictionary (337 keys).
.config/hypr/scripts/quickshell/Main.qml Live-reloads translations when uiLanguage changes in settings.
.config/hypr/scripts/quickshell/TopBar.qml Translates topbar date fragments and various status labels; reloads translations on settings changes.
.config/hypr/scripts/quickshell/calendar/CalendarPopup.qml Translates calendar/month/day labels and weather descriptions/schedule strings.
.config/hypr/scripts/quickshell/settings/SettingsPopup.qml Translates settings UI and adds language selector controls.
.config/hypr/scripts/quickshell/focustime/FocusTimePopup.qml Translates FocusTime labels and adjusts date formatting for Russian.
.config/hypr/scripts/quickshell/monitors/MonitorPopup.qml Translates Apply/Apply All; also changes wallpaper reload command.
.config/hypr/scripts/quickshell/watchers/bt_fetch.sh Localizes Bluetooth toggle notifications based on uiLanguage.
.config/hypr/scripts/screenshot.sh Localizes screenshot/recording notifications and missing-deps error based on uiLanguage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .config/hypr/scripts/quickshell/Config.qml Outdated
Comment thread .config/hypr/scripts/quickshell/Config.qml
Comment thread .config/hypr/scripts/quickshell/focustime/FocusTimePopup.qml Outdated
Comment thread .config/hypr/scripts/quickshell/calendar/CalendarPopup.qml Outdated
Comment thread .config/hypr/scripts/screenshot.sh
Comment thread .config/hypr/scripts/quickshell/monitors/MonitorPopup.qml
Comment thread .config/hypr/scripts/quickshell/settings/SettingsPopup.qml Outdated
- Config.qml: Avoid bash -c for reading translations to prevent shell injection
- Config.qml: Use execDetached for notify-send instead of bash -c string concat
- FocusTimePopup.qml: Use translated month names for non-Russian locales
- CalendarPopup.qml: Localize the hardcoded 'LOADING...' weather fallback
- screenshot.sh: Safely parse language without grep stderr output
- MonitorPopup.qml: Revert accidental awww to swww change
- SettingsPopup.qml: Update 'Requires QuickShell reload' fallback to reflect live reload
@ilyamiro
ilyamiro force-pushed the master branch 5 times, most recently from cbab0e0 to 03cc319 Compare May 12, 2026 16:04
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.

[Feature Request] UI Language toggle + [Bug] weather.sh breaks on non-English locales + missing rain/fog icons

3 participants