1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-14 17:52:10 -04:00

feat: add setting to change and hotreload locale (#1817)

* feat: add setting to change and hotreload locale

* fix: typo in component id

* feat: add persistent locale setting

* feat: wrap useLocale in a settings set hook, enable locale hotreload when editing settings file

* chore: update translation and settings file

* feat: enable fuzzy search in locale setting

* fix: regenerate translations with official plugins cloned

* fix: revert back to system's locale for displaying certain time formats
This commit is contained in:
Jonas Bloch
2026-02-26 22:00:17 +01:00
committed by GitHub
parent f82d7610e3
commit 1fe72e1a66
21 changed files with 819 additions and 536 deletions

View File

@@ -8,7 +8,7 @@ import Quickshell.Io
Singleton { Singleton {
id: root id: root
readonly property string _rawLocale: Qt.locale().name readonly property string _rawLocale: SettingsData.locale === "" ? Qt.locale().name : SettingsData.locale
readonly property string _lang: _rawLocale.split(/[_-]/)[0] readonly property string _lang: _rawLocale.split(/[_-]/)[0]
readonly property var _candidates: { readonly property var _candidates: {
const fullUnderscore = _rawLocale; const fullUnderscore = _rawLocale;
@@ -21,7 +21,8 @@ Singleton {
readonly property url translationsFolder: Qt.resolvedUrl("../translations/poexports") readonly property url translationsFolder: Qt.resolvedUrl("../translations/poexports")
property string currentLocale: "en" readonly property alias folder: dir.folder
property var presentLocales: ({ "en": Qt.locale("en") })
property var translations: ({}) property var translations: ({})
property bool translationsLoaded: false property bool translationsLoaded: false
@@ -34,8 +35,10 @@ Singleton {
showDirs: false showDirs: false
showDotAndDotDot: false showDotAndDotDot: false
onStatusChanged: if (status === FolderListModel.Ready) onStatusChanged: if (status === FolderListModel.Ready) {
root._pickTranslation() root._loadPresentLocales();
root._pickTranslation();
}
} }
FileView { FileView {
@@ -46,32 +49,42 @@ Singleton {
try { try {
root.translations = JSON.parse(text()); root.translations = JSON.parse(text());
root.translationsLoaded = true; root.translationsLoaded = true;
console.info(`I18n: Loaded translations for '${root.currentLocale}' ` + `(${Object.keys(root.translations).length} contexts)`); console.info(`I18n: Loaded translations for '${SettingsData.locale}' (${Object.keys(root.translations).length} contexts)`);
} catch (e) { } catch (e) {
console.warn(`I18n: Error parsing '${root.currentLocale}':`, e, "- falling back to English"); console.warn(`I18n: Error parsing '${SettingsData.locale}':`, e, "- falling back to English");
root._fallbackToEnglish(); root._fallbackToEnglish();
} }
} }
onLoadFailed: error => { onLoadFailed: error => {
console.warn(`I18n: Failed to load '${root.currentLocale}' (${error}), ` + "falling back to English"); console.warn(`I18n: Failed to load '${SettingsData.locale}' (${error}), ` + "falling back to English");
root._fallbackToEnglish(); root._fallbackToEnglish();
} }
} }
function _pickTranslation() { // for replacing Qt.locale()
const present = new Set(); function locale() {
return presentLocales[SettingsData.locale] ?? presentLocales["en"];
}
function _loadPresentLocales() {
if (Object.keys(presentLocales).length > 1) {
return; // already loaded
}
for (let i = 0; i < dir.count; i++) { for (let i = 0; i < dir.count; i++) {
const name = dir.get(i, "fileName"); // e.g. "zh_CN.json" const name = dir.get(i, "fileName"); // e.g. "zh_CN.json"
if (name && name.endsWith(".json")) { if (name && name.endsWith(".json")) {
present.add(name.slice(0, -5)); const shortName = name.slice(0, -5);
presentLocales[shortName] = Qt.locale(shortName);
} }
} }
}
function _pickTranslation() {
for (let i = 0; i < _candidates.length; i++) { for (let i = 0; i < _candidates.length; i++) {
const cand = _candidates[i]; const cand = _candidates[i];
if (present.has(cand)) { if (presentLocales[cand] !== undefined) {
_useLocale(cand, dir.folder + "/" + cand + ".json"); SettingsData.set("locale", cand);
return; return;
} }
} }
@@ -79,8 +92,7 @@ Singleton {
_fallbackToEnglish(); _fallbackToEnglish();
} }
function _useLocale(localeTag, fileUrl) { function useLocale(localeTag, fileUrl) {
currentLocale = localeTag;
_selectedPath = fileUrl; _selectedPath = fileUrl;
translationsLoaded = false; translationsLoaded = false;
translations = ({}); translations = ({});
@@ -88,7 +100,6 @@ Singleton {
} }
function _fallbackToEnglish() { function _fallbackToEnglish() {
currentLocale = "en";
_selectedPath = ""; _selectedPath = "";
translationsLoaded = false; translationsLoaded = false;
translations = ({}); translations = ({});

View File

@@ -149,6 +149,7 @@ Singleton {
property int mangoLayoutRadiusOverride: -1 property int mangoLayoutRadiusOverride: -1
property int mangoLayoutBorderSize: -1 property int mangoLayoutBorderSize: -1
property string locale: ""
property bool use24HourClock: true property bool use24HourClock: true
property bool showSeconds: false property bool showSeconds: false
property bool padHours12Hour: false property bool padHours12Hour: false
@@ -1130,13 +1131,18 @@ Singleton {
Quickshell.execDetached(["sh", "-lc", script]); Quickshell.execDetached(["sh", "-lc", script]);
} }
function updateLocale() {
I18n.useLocale(locale, locale.startsWith("en") ? "" : I18n.folder + "/" + locale + ".json");
}
readonly property var _hooks: ({ readonly property var _hooks: ({
"applyStoredTheme": applyStoredTheme, "applyStoredTheme": applyStoredTheme,
"regenSystemThemes": regenSystemThemes, "regenSystemThemes": regenSystemThemes,
"updateCompositorLayout": updateCompositorLayout, "updateCompositorLayout": updateCompositorLayout,
"applyStoredIconTheme": applyStoredIconTheme, "applyStoredIconTheme": applyStoredIconTheme,
"updateBarConfigs": updateBarConfigs, "updateBarConfigs": updateBarConfigs,
"updateCompositorCursor": updateCompositorCursor "updateCompositorCursor": updateCompositorCursor,
"updateLocale": updateLocale,
}) })
function set(key, value) { function set(key, value) {
@@ -2640,6 +2646,7 @@ Singleton {
_hasLoaded = true; _hasLoaded = true;
applyStoredTheme(); applyStoredTheme();
updateCompositorCursor(); updateCompositorCursor();
updateLocale();
} catch (e) { } catch (e) {
_parseError = true; _parseError = true;
const msg = e.message; const msg = e.message;

View File

@@ -32,6 +32,7 @@ var SPEC = {
mangoLayoutRadiusOverride: { def: -1, onChange: "updateCompositorLayout" }, mangoLayoutRadiusOverride: { def: -1, onChange: "updateCompositorLayout" },
mangoLayoutBorderSize: { def: -1, onChange: "updateCompositorLayout" }, mangoLayoutBorderSize: { def: -1, onChange: "updateCompositorLayout" },
locale: { def: "", onChange: "updateLocale" },
use24HourClock: { def: true }, use24HourClock: { def: true },
showSeconds: { def: false }, showSeconds: { def: false },
padHours12Hour: { def: false }, padHours12Hour: { def: false },

View File

@@ -470,7 +470,22 @@ FocusScope {
onActiveChanged: { onActiveChanged: {
if (active && item) if (active && item)
Qt.callLater(() => item.forceActiveFocus()); Qt.callLater(() => item.forceActiveFocus());
}
}
Loader {
id: localeLoader
anchors.fill: parent
active: root.currentIndex === 30
visible: active
focus: active
sourceComponent: LocaleTab {}
onActiveChanged: {
if (active && item)
Qt.callLater(() => item.forceActiveFocus());
} }
} }
} }

View File

@@ -246,6 +246,12 @@ Rectangle {
"icon": "headphones", "icon": "headphones",
"tabIndex": 29 "tabIndex": 29
}, },
{
"id": "locale",
"text": I18n.tr("Locale"),
"icon": "language",
"tabIndex": 30
},
{ {
"id": "clipboard", "id": "clipboard",
"text": I18n.tr("Clipboard"), "text": I18n.tr("Clipboard"),

View File

@@ -271,8 +271,8 @@ Item {
text: { text: {
if (SettingsData.clockDateFormat && SettingsData.clockDateFormat.length > 0) if (SettingsData.clockDateFormat && SettingsData.clockDateFormat.length > 0)
return systemClock.date?.toLocaleDateString(Qt.locale(), SettingsData.clockDateFormat) ?? ""; return systemClock.date?.toLocaleDateString(I18n.locale(), SettingsData.clockDateFormat) ?? "";
return systemClock.date?.toLocaleDateString(Qt.locale(), "ddd, MMM d") ?? ""; return systemClock.date?.toLocaleDateString(I18n.locale(), "ddd, MMM d") ?? "";
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: root.accentColor color: root.accentColor
@@ -324,8 +324,8 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text: { text: {
if (SettingsData.clockDateFormat && SettingsData.clockDateFormat.length > 0) if (SettingsData.clockDateFormat && SettingsData.clockDateFormat.length > 0)
return systemClock.date?.toLocaleDateString(Qt.locale(), SettingsData.clockDateFormat) ?? ""; return systemClock.date?.toLocaleDateString(I18n.locale(), SettingsData.clockDateFormat) ?? "";
return systemClock.date?.toLocaleDateString(Qt.locale(), "ddd, MMM d") ?? ""; return systemClock.date?.toLocaleDateString(I18n.locale(), "ddd, MMM d") ?? "";
} }
font.pixelSize: digitalRoot.smallSize font.pixelSize: digitalRoot.smallSize
color: Theme.withAlpha(root.accentColor, 0.7) color: Theme.withAlpha(root.accentColor, 0.7)
@@ -528,7 +528,7 @@ Item {
StyledText { StyledText {
visible: stackedRoot.hasDate visible: stackedRoot.hasDate
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text: systemClock.date?.toLocaleDateString(Qt.locale(), "MMM dd") ?? "" text: systemClock.date?.toLocaleDateString(I18n.locale(), "MMM dd") ?? ""
font.pixelSize: stackedRoot.smallSize * 0.7 font.pixelSize: stackedRoot.smallSize * 0.7
color: Theme.withAlpha(root.accentColor, 0.7) color: Theme.withAlpha(root.accentColor, 0.7)
} }

View File

@@ -129,7 +129,7 @@ BasePill {
StyledText { StyledText {
text: { text: {
const locale = Qt.locale(); const locale = I18n.locale();
const dateFormatShort = locale.dateFormat(Locale.ShortFormat); const dateFormatShort = locale.dateFormat(Locale.ShortFormat);
const dayFirst = dateFormatShort.indexOf('d') < dateFormatShort.indexOf('M'); const dayFirst = dateFormatShort.indexOf('d') < dateFormatShort.indexOf('M');
const value = dayFirst ? String(systemClock?.date?.getDate()).padStart(2, '0') : String(systemClock?.date?.getMonth() + 1).padStart(2, '0'); const value = dayFirst ? String(systemClock?.date?.getDate()).padStart(2, '0') : String(systemClock?.date?.getMonth() + 1).padStart(2, '0');
@@ -144,7 +144,7 @@ BasePill {
StyledText { StyledText {
text: { text: {
const locale = Qt.locale(); const locale = I18n.locale();
const dateFormatShort = locale.dateFormat(Locale.ShortFormat); const dateFormatShort = locale.dateFormat(Locale.ShortFormat);
const dayFirst = dateFormatShort.indexOf('d') < dateFormatShort.indexOf('M'); const dayFirst = dateFormatShort.indexOf('d') < dateFormatShort.indexOf('M');
const value = dayFirst ? String(systemClock?.date?.getDate()).padStart(2, '0') : String(systemClock?.date?.getMonth() + 1).padStart(2, '0'); const value = dayFirst ? String(systemClock?.date?.getDate()).padStart(2, '0') : String(systemClock?.date?.getMonth() + 1).padStart(2, '0');
@@ -165,7 +165,7 @@ BasePill {
StyledText { StyledText {
text: { text: {
const locale = Qt.locale(); const locale = I18n.locale();
const dateFormatShort = locale.dateFormat(Locale.ShortFormat); const dateFormatShort = locale.dateFormat(Locale.ShortFormat);
const dayFirst = dateFormatShort.indexOf('d') < dateFormatShort.indexOf('M'); const dayFirst = dateFormatShort.indexOf('d') < dateFormatShort.indexOf('M');
const value = dayFirst ? String(systemClock?.date?.getMonth() + 1).padStart(2, '0') : String(systemClock?.date?.getDate()).padStart(2, '0'); const value = dayFirst ? String(systemClock?.date?.getMonth() + 1).padStart(2, '0') : String(systemClock?.date?.getDate()).padStart(2, '0');
@@ -180,7 +180,7 @@ BasePill {
StyledText { StyledText {
text: { text: {
const locale = Qt.locale(); const locale = I18n.locale();
const dateFormatShort = locale.dateFormat(Locale.ShortFormat); const dateFormatShort = locale.dateFormat(Locale.ShortFormat);
const dayFirst = dateFormatShort.indexOf('d') < dateFormatShort.indexOf('M'); const dayFirst = dateFormatShort.indexOf('d') < dateFormatShort.indexOf('M');
const value = dayFirst ? String(systemClock?.date?.getMonth() + 1).padStart(2, '0') : String(systemClock?.date?.getDate()).padStart(2, '0'); const value = dayFirst ? String(systemClock?.date?.getMonth() + 1).padStart(2, '0') : String(systemClock?.date?.getDate()).padStart(2, '0');
@@ -311,9 +311,9 @@ BasePill {
id: dateText id: dateText
text: { text: {
if (SettingsData.clockDateFormat && SettingsData.clockDateFormat.length > 0) { if (SettingsData.clockDateFormat && SettingsData.clockDateFormat.length > 0) {
return systemClock?.date?.toLocaleDateString(Qt.locale(), SettingsData.clockDateFormat); return systemClock?.date?.toLocaleDateString(I18n.locale(), SettingsData.clockDateFormat);
} }
return systemClock?.date?.toLocaleDateString(Qt.locale(), "ddd d"); return systemClock?.date?.toLocaleDateString(I18n.locale(), "ddd d");
} }
font.pixelSize: clockRow.fontSize font.pixelSize: clockRow.fontSize
color: Theme.widgetTextColor color: Theme.widgetTextColor

View File

@@ -179,7 +179,7 @@ Rectangle {
StyledText { StyledText {
width: parent.width - 56 width: parent.width - 56
height: 28 height: 28
text: calendarGrid.displayDate.toLocaleDateString(Qt.locale(), "MMMM yyyy") text: calendarGrid.displayDate.toLocaleDateString(I18n.locale(), "MMMM yyyy")
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText color: Theme.surfaceText
font.weight: Font.Medium font.weight: Font.Medium
@@ -223,11 +223,10 @@ Rectangle {
Repeater { Repeater {
model: { model: {
const days = []; const days = [];
const loc = Qt.locale(); const qtFirst = Qt.locale().firstDayOfWeek;
const qtFirst = loc.firstDayOfWeek;
for (let i = 0; i < 7; ++i) { for (let i = 0; i < 7; ++i) {
const qtDay = ((qtFirst - 1 + i) % 7) + 1; const qtDay = ((qtFirst - 1 + i) % 7) + 1;
days.push(loc.dayName(qtDay, Locale.ShortFormat)); days.push(I18n.locale().dayName(qtDay, Locale.ShortFormat));
} }
return days; return days;
} }

View File

@@ -99,7 +99,7 @@ Card {
} }
StyledText { StyledText {
text: systemClock?.date?.toLocaleDateString(Qt.locale(), "MMM dd") text: systemClock?.date?.toLocaleDateString(I18n.locale(), "MMM dd")
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter

View File

@@ -218,7 +218,7 @@ Item {
property string fullTimeStr: { property string fullTimeStr: {
const format = GreetdSettings.getEffectiveTimeFormat(); const format = GreetdSettings.getEffectiveTimeFormat();
return systemClock.date.toLocaleTimeString(Qt.locale(), format); return systemClock.date.toLocaleTimeString(I18n.locale(), format);
} }
property var timeParts: fullTimeStr.split(':') property var timeParts: fullTimeStr.split(':')
property string hours: timeParts[0] || "" property string hours: timeParts[0] || ""
@@ -328,9 +328,9 @@ Item {
anchors.topMargin: 4 anchors.topMargin: 4
text: { text: {
if (GreetdSettings.lockDateFormat && GreetdSettings.lockDateFormat.length > 0) { if (GreetdSettings.lockDateFormat && GreetdSettings.lockDateFormat.length > 0) {
return systemClock.date.toLocaleDateString(Qt.locale(), GreetdSettings.lockDateFormat); return systemClock.date.toLocaleDateString(I18n.locale(), GreetdSettings.lockDateFormat);
} }
return systemClock.date.toLocaleDateString(Qt.locale(), Locale.LongFormat); return systemClock.date.toLocaleDateString(I18n.locale(), Locale.LongFormat);
} }
font.pixelSize: Theme.fontSizeXLarge font.pixelSize: Theme.fontSizeXLarge
color: "white" color: "white"

View File

@@ -333,9 +333,9 @@ Item {
visible: SettingsData.lockScreenShowDate visible: SettingsData.lockScreenShowDate
text: { text: {
if (SettingsData.lockDateFormat && SettingsData.lockDateFormat.length > 0) { if (SettingsData.lockDateFormat && SettingsData.lockDateFormat.length > 0) {
return systemClock.date.toLocaleDateString(Qt.locale(), SettingsData.lockDateFormat); return systemClock.date.toLocaleDateString(I18n.locale(), SettingsData.lockDateFormat);
} }
return systemClock.date.toLocaleDateString(Qt.locale(), Locale.LongFormat); return systemClock.date.toLocaleDateString(I18n.locale(), Locale.LongFormat);
} }
font.pixelSize: Theme.fontSizeXLarge font.pixelSize: Theme.fontSizeXLarge
color: "white" color: "white"

View File

@@ -0,0 +1,63 @@
import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
import qs.Modules.Settings.Widgets
Item {
id: root
function capitalizeNativeLanguageName(localeCode) {
if (I18n.presentLocales[localeCode] == undefined) {
return;
}
const nativeName = I18n.presentLocales[localeCode].nativeLanguageName;
return nativeName[0].toUpperCase() + nativeName.slice(1);
}
DankFlickable {
anchors.fill: parent
clip: true
contentHeight: mainColumn.height + Theme.spacingXL
contentWidth: width
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
SettingsCard {
tab: "locale"
tags: ["locale", "language", "country"]
title: I18n.tr("Locale Settings")
iconName: "language"
SettingsDropdownRow {
id: localeDropdown
tab: "locale"
tags: ["locale", "language", "country"]
settingKey: "locale"
text: I18n.tr("Current Locale")
description: I18n.tr("Change the locale used by the DMS interface.")
options: Object.keys(I18n.presentLocales).map(root.capitalizeNativeLanguageName)
enableFuzzySearch: true
Component.onCompleted: {
currentValue = root.capitalizeNativeLanguageName(SettingsData.locale);
}
onValueChanged: value => {
for (let code of Object.keys(I18n.presentLocales)) {
if (root.capitalizeNativeLanguageName(code) === value) {
SettingsData.set("locale", code);
return;
}
}
}
}
}
}
}
}

View File

@@ -74,7 +74,7 @@ Item {
tags: ["date", "format", "topbar"] tags: ["date", "format", "topbar"]
settingKey: "clockDateFormat" settingKey: "clockDateFormat"
text: I18n.tr("Top Bar Format") text: I18n.tr("Top Bar Format")
description: "Preview: " + (SettingsData.clockDateFormat ? new Date().toLocaleDateString(Qt.locale(), SettingsData.clockDateFormat) : new Date().toLocaleDateString(Qt.locale(), "ddd d")) description: "Preview: " + (SettingsData.clockDateFormat ? new Date().toLocaleDateString(I18n.locale(), SettingsData.clockDateFormat) : new Date().toLocaleDateString(I18n.locale(), "ddd d"))
options: [I18n.tr("System Default", "date format option"), I18n.tr("Day Date", "date format option"), I18n.tr("Day Month Date", "date format option"), I18n.tr("Month Date", "date format option"), I18n.tr("Numeric (M/D)", "date format option"), I18n.tr("Numeric (D/M)", "date format option"), I18n.tr("Full with Year", "date format option"), I18n.tr("ISO Date", "date format option"), I18n.tr("Full Day & Month", "date format option"), I18n.tr("Custom...", "date format option")] options: [I18n.tr("System Default", "date format option"), I18n.tr("Day Date", "date format option"), I18n.tr("Day Month Date", "date format option"), I18n.tr("Month Date", "date format option"), I18n.tr("Numeric (M/D)", "date format option"), I18n.tr("Numeric (D/M)", "date format option"), I18n.tr("Full with Year", "date format option"), I18n.tr("ISO Date", "date format option"), I18n.tr("Full Day & Month", "date format option"), I18n.tr("Custom...", "date format option")]
currentValue: { currentValue: {
if (!SettingsData.clockDateFormat || SettingsData.clockDateFormat.length === 0) if (!SettingsData.clockDateFormat || SettingsData.clockDateFormat.length === 0)
@@ -161,7 +161,7 @@ Item {
tags: ["date", "format", "lock", "screen"] tags: ["date", "format", "lock", "screen"]
settingKey: "lockDateFormat" settingKey: "lockDateFormat"
text: I18n.tr("Lock Screen Format") text: I18n.tr("Lock Screen Format")
description: "Preview: " + (SettingsData.lockDateFormat ? new Date().toLocaleDateString(Qt.locale(), SettingsData.lockDateFormat) : new Date().toLocaleDateString(Qt.locale(), Locale.LongFormat)) description: "Preview: " + (SettingsData.lockDateFormat ? new Date().toLocaleDateString(I18n.locale(), SettingsData.lockDateFormat) : new Date().toLocaleDateString(I18n.locale(), Locale.LongFormat))
options: [I18n.tr("System Default", "date format option"), I18n.tr("Day Date", "date format option"), I18n.tr("Day Month Date", "date format option"), I18n.tr("Month Date", "date format option"), I18n.tr("Numeric (M/D)", "date format option"), I18n.tr("Numeric (D/M)", "date format option"), I18n.tr("Full with Year", "date format option"), I18n.tr("ISO Date", "date format option"), I18n.tr("Full Day & Month", "date format option"), I18n.tr("Custom...", "date format option")] options: [I18n.tr("System Default", "date format option"), I18n.tr("Day Date", "date format option"), I18n.tr("Day Month Date", "date format option"), I18n.tr("Month Date", "date format option"), I18n.tr("Numeric (M/D)", "date format option"), I18n.tr("Numeric (D/M)", "date format option"), I18n.tr("Full with Year", "date format option"), I18n.tr("ISO Date", "date format option"), I18n.tr("Full Day & Month", "date format option"), I18n.tr("Custom...", "date format option")]
currentValue: { currentValue: {
if (!SettingsData.lockDateFormat || SettingsData.lockDateFormat.length === 0) if (!SettingsData.lockDateFormat || SettingsData.lockDateFormat.length === 0)

View File

@@ -128,7 +128,7 @@ DesktopPluginComponent {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: Theme.spacingXS anchors.bottomMargin: Theme.spacingXS
text: systemClock.date?.toLocaleDateString(Qt.locale(), "ddd, MMM d") ?? "" text: systemClock.date?.toLocaleDateString(I18n.locale(), "ddd, MMM d") ?? ""
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium font.weight: Font.Medium
color: Theme.surfaceText color: Theme.surfaceText
@@ -163,7 +163,7 @@ DesktopPluginComponent {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.top: timeText.bottom anchors.top: timeText.bottom
anchors.topMargin: Theme.spacingXS anchors.topMargin: Theme.spacingXS
text: systemClock.date?.toLocaleDateString(Qt.locale(), "ddd, MMM d") ?? "" text: systemClock.date?.toLocaleDateString(I18n.locale(), "ddd, MMM d") ?? ""
font.pixelSize: digitalRoot.dateFontSize font.pixelSize: digitalRoot.dateFontSize
color: Theme.surfaceText color: Theme.surfaceText
} }

View File

@@ -157,12 +157,12 @@ Singleton {
// Parse start and end dates using detected format // Parse start and end dates using detected format
let startDate, endDate let startDate, endDate
if (event['start-date']) { if (event['start-date']) {
startDate = Date.fromLocaleString(Qt.locale(), event['start-date'], root.khalDateFormat) startDate = Date.fromLocaleString(I18n.locale(), event['start-date'], root.khalDateFormat)
} else { } else {
startDate = new Date() startDate = new Date()
} }
if (event['end-date']) { if (event['end-date']) {
endDate = Date.fromLocaleString(Qt.locale(), event['end-date'], root.khalDateFormat) endDate = Date.fromLocaleString(I18n.locale(), event['end-date'], root.khalDateFormat)
} else { } else {
endDate = new Date(startDate) endDate = new Date(startDate)
} }

View File

@@ -252,7 +252,7 @@ Singleton {
if (daysDiff === 0) if (daysDiff === 0)
return timeStr; return timeStr;
try { try {
const localeName = (typeof Qt !== "undefined" && Qt.locale) ? Qt.locale().name : "en-US"; const localeName = (typeof I18n !== "undefined" && I18n.locale) ? I18n.locale().name : "en-US";
const weekday = date.toLocaleDateString(localeName, { const weekday = date.toLocaleDateString(localeName, {
weekday: "long" weekday: "long"
}); });
@@ -695,7 +695,7 @@ Singleton {
} }
try { try {
const localeName = (typeof Qt !== "undefined" && Qt.locale) ? Qt.locale().name : "en-US"; const localeName = (typeof I18n !== "undefined" && I18n.locale) ? I18n.locale().name : "en-US";
const weekday = time.toLocaleDateString(localeName, { const weekday = time.toLocaleDateString(localeName, {
weekday: "long" weekday: "long"
}); });

View File

@@ -444,7 +444,7 @@ Singleton {
const date = new Date(); const date = new Date();
date.setDate(date.getDate() + index); date.setDate(date.getDate() + index);
const locale = Qt.locale(); const locale = I18n.locale();
return locale.dayName(date.getDay(), Locale.ShortFormat); return locale.dayName(date.getDay(), Locale.ShortFormat);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import re
import json import json
import re
from collections import Counter from collections import Counter
from pathlib import Path from pathlib import Path
@@ -82,7 +82,15 @@ CATEGORY_KEYWORDS = {
"Displays": ["monitor", "screen", "resolution"], "Displays": ["monitor", "screen", "resolution"],
"Desktop Widgets": ["conky", "desktop clock"], "Desktop Widgets": ["conky", "desktop clock"],
"Audio": ["sound", "volume", "speaker", "microphone", "headphones", "pipewire"], "Audio": ["sound", "volume", "speaker", "microphone", "headphones", "pipewire"],
"Window Rules": ["window", "rules", "matching", "floating", "fullscreen", "opacity"], "Window Rules": [
"window",
"rules",
"matching",
"floating",
"fullscreen",
"opacity",
],
"Locale": ["locale", "language", "country"],
} }
TAB_INDEX_MAP = { TAB_INDEX_MAP = {
@@ -115,6 +123,7 @@ TAB_INDEX_MAP = {
"DesktopWidgetsTab.qml": 27, "DesktopWidgetsTab.qml": 27,
"WindowRulesTab.qml": 28, "WindowRulesTab.qml": 28,
"AudioTab.qml": 29, "AudioTab.qml": 29,
"LocaleTab.qml": 30,
} }
TAB_CATEGORY_MAP = { TAB_CATEGORY_MAP = {
@@ -147,6 +156,7 @@ TAB_CATEGORY_MAP = {
27: "Desktop Widgets", 27: "Desktop Widgets",
28: "Window Rules", 28: "Window Rules",
29: "Audio", 29: "Audio",
30: "Locale",
} }
SEARCHABLE_COMPONENTS = [ SEARCHABLE_COMPONENTS = [

View File

@@ -3925,6 +3925,27 @@
], ],
"description": "Automatically lock the screen when DMS starts" "description": "Automatically lock the screen when DMS starts"
}, },
{
"section": "lockBeforeSuspend",
"label": "Lock before suspend",
"tabIndex": 11,
"category": "Lock Screen",
"keywords": [
"automatic",
"automatically",
"before",
"lock",
"login",
"password",
"prepares",
"screen",
"security",
"sleep",
"suspend",
"system"
],
"description": "Automatically lock the screen when the system prepares to suspend"
},
{ {
"section": "lockScreenNotificationMode", "section": "lockScreenNotificationMode",
"label": "Notification Display", "label": "Notification Display",
@@ -5849,27 +5870,6 @@
"icon": "schedule", "icon": "schedule",
"description": "Gradually fade the screen before locking with a configurable grace period" "description": "Gradually fade the screen before locking with a configurable grace period"
}, },
{
"section": "lockBeforeSuspend",
"label": "Lock before suspend",
"tabIndex": 21,
"category": "Power & Sleep",
"keywords": [
"automatically",
"before",
"energy",
"lock",
"power",
"prepares",
"screen",
"security",
"shutdown",
"sleep",
"suspend",
"system"
],
"description": "Automatically lock the screen when the system prepares to suspend"
},
{ {
"section": "fadeToLockGracePeriod", "section": "fadeToLockGracePeriod",
"label": "Lock fade grace period", "label": "Lock fade grace period",
@@ -6437,5 +6437,33 @@
"volume" "volume"
], ],
"icon": "computer" "icon": "computer"
},
{
"section": "_tab_30",
"label": "Locale",
"tabIndex": 30,
"category": "Locale",
"keywords": [
"country",
"language",
"locale"
],
"icon": "language"
},
{
"section": "locale",
"label": "Locale Settings",
"tabIndex": 30,
"category": "Locale",
"keywords": [
"change",
"country",
"interface",
"language",
"locale",
"settings"
],
"icon": "language",
"description": "Change the locale used by the DMS interface."
} }
] ]

View File

@@ -2043,6 +2043,13 @@
"reference": "", "reference": "",
"comment": "" "comment": ""
}, },
{
"term": "Change the locale used by the DMS interface.",
"translation": "",
"context": "",
"reference": "",
"comment": ""
},
{ {
"term": "Channel", "term": "Channel",
"translation": "", "translation": "",
@@ -3114,6 +3121,13 @@
"reference": "", "reference": "",
"comment": "" "comment": ""
}, },
{
"term": "Current Locale",
"translation": "",
"context": "",
"reference": "",
"comment": ""
},
{ {
"term": "Current Monitor", "term": "Current Monitor",
"translation": "", "translation": "",
@@ -3849,6 +3863,13 @@
"reference": "", "reference": "",
"comment": "" "comment": ""
}, },
{
"term": "Disk Usage Display",
"translation": "",
"context": "",
"reference": "",
"comment": ""
},
{ {
"term": "Disks", "term": "Disks",
"translation": "", "translation": "",
@@ -6936,6 +6957,20 @@
"reference": "", "reference": "",
"comment": "" "comment": ""
}, },
{
"term": "Locale",
"translation": "",
"context": "",
"reference": "",
"comment": ""
},
{
"term": "Locale Settings",
"translation": "",
"context": "",
"reference": "",
"comment": ""
},
{ {
"term": "Location", "term": "Location",
"translation": "", "translation": "",
@@ -10184,6 +10219,20 @@
"reference": "", "reference": "",
"comment": "" "comment": ""
}, },
{
"term": "Remaining",
"translation": "",
"context": "",
"reference": "",
"comment": ""
},
{
"term": "Remaining / Total",
"translation": "",
"context": "",
"reference": "",
"comment": ""
},
{ {
"term": "Remove", "term": "Remove",
"translation": "", "translation": "",
@@ -11549,6 +11598,13 @@
"reference": "", "reference": "",
"comment": "" "comment": ""
}, },
{
"term": "Show Memory in GB",
"translation": "",
"context": "",
"reference": "",
"comment": ""
},
{ {
"term": "Show Network", "term": "Show Network",
"translation": "", "translation": "",
@@ -11661,6 +11717,13 @@
"reference": "", "reference": "",
"comment": "" "comment": ""
}, },
{
"term": "Show Swap",
"translation": "",
"context": "",
"reference": "",
"comment": ""
},
{ {
"term": "Show System Date", "term": "Show System Date",
"translation": "", "translation": "",
@@ -11766,6 +11829,13 @@
"reference": "", "reference": "",
"comment": "" "comment": ""
}, },
{
"term": "Show in GB",
"translation": "",
"context": "",
"reference": "",
"comment": ""
},
{ {
"term": "Show launcher overlay when typing in Niri overview. Disable to use another launcher.", "term": "Show launcher overlay when typing in Niri overview. Disable to use another launcher.",
"translation": "", "translation": "",
@@ -12914,6 +12984,13 @@
"reference": "", "reference": "",
"comment": "" "comment": ""
}, },
{
"term": "Total",
"translation": "",
"context": "",
"reference": "",
"comment": ""
},
{ {
"term": "Total Jobs", "term": "Total Jobs",
"translation": "", "translation": "",