feat: i18n localization system + complete Russian translation#66
feat: i18n localization system + complete Russian translation#66Volfheim wants to merge 4 commits into
Conversation
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
|
Did you write this with AI? |
|
It seems so. But sure, i think i will review and probably merge this. |
|
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! |
|
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. 🙃 |
|
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. |
|
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. |
|
Про цельсий и т.д я имею ввиду что они вообще не переведены. Они на английском так и были. Я не про склонение говорил |
- settings.box.temp_desc: 'Celsius / Fahrenheit / K' → 'Цельсий / Фаренгейт / Кельвин' - Replace all 'напр.' abbreviations with full 'например' for cleaner Russian UI
|
Fixed both issues:
Thanks for the review! |
|
И всё же вопрос множественное число оставить или единственное, попробовал оба варианта, в поиске по настройкам сейчас единственное число как ты и написал, а в ui множественное как я изначально сделал, и всё же склоняюсь к множественному, но в общем как скажешь 👍 |
|
Ну просто это "Единицы измерения" и их не склонять лучше. Оставь в единственном |
|
Сделано, заодно (не юзал поиск по настройкам особо) заметил недоперевод в плейсхолдере под поиском, его тоже в ключи добавил и перевёл |
There was a problem hiding this comment.
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 persistsuiLanguageinsettings.json. - Replaces many hardcoded UI strings in QML with translation lookups and adds an in-UI language selector.
- Localizes user-facing notifications in
screenshot.shandbt_fetch.shbased onuiLanguage.
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.
- 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
cbab0e0 to
03cc319
Compare

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 missingi18n/*.json— external translation dictionaries. Community can add new languages (i18n/de.json,i18n/fr.json, etc.) without touching QMLuiLanguage— persisted insettings.json, live-reloaded viainotifywait(no shell restart needed)What is covered (11 files changed, +626 / -95)
tr(),loadTranslations(),langUpdateTrigger)Design decisions
uiLanguageis not set oren.jsonis empty, everything works exactly as before4 мая, not4 Май) and Russian day/month order (DD MonthvsMonth DD)uiLanguagefromsettings.jsonviagrepfor notification translation, gracefully falling back to EnglishHow to add a new language
i18n/xx.jsonwith the same keys asru.jsonSettingsPopup.qmlTesting
Tested on CachyOS (Arch) with Hyprland, Quickshell, Iosevka Nerd Font,
ru_RU.UTF-8locale.