1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-03 20:32:07 -04:00

i18n: decouple time and language locale

fixes #1876
This commit is contained in:
bbedward
2026-03-01 15:17:15 -05:00
parent f4a10de790
commit db53a9a719
5 changed files with 349 additions and 114 deletions

View File

@@ -1,5 +1,6 @@
pragma Singleton pragma Singleton
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import Qt.labs.folderlistmodel import Qt.labs.folderlistmodel
import Quickshell import Quickshell
@@ -24,7 +25,9 @@ Singleton {
readonly property url translationsFolder: Qt.resolvedUrl("../translations/poexports") readonly property url translationsFolder: Qt.resolvedUrl("../translations/poexports")
readonly property alias folder: dir.folder readonly property alias folder: dir.folder
property var presentLocales: ({ "en": Qt.locale("en") }) property var presentLocales: ({
"en": Qt.locale("en")
})
property var translations: ({}) property var translations: ({})
property bool translationsLoaded: false property bool translationsLoaded: false
@@ -65,7 +68,9 @@ Singleton {
} }
function locale() { function locale() {
return presentLocales[_resolvedLocale] ?? presentLocales["en"]; if (SessionData.timeLocale)
return Qt.locale(SessionData.timeLocale);
return Qt.locale();
} }
function _loadPresentLocales() { function _loadPresentLocales() {
@@ -84,7 +89,8 @@ Singleton {
function _pickTranslation() { 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 (presentLocales[cand] === undefined) continue; if (presentLocales[cand] === undefined)
continue;
_resolvedLocale = cand; _resolvedLocale = cand;
useLocale(cand, cand.startsWith("en") ? "" : translationsFolder + "/" + cand + ".json"); useLocale(cand, cand.startsWith("en") ? "" : translationsFolder + "/" + cand + ".json");
return; return;

View File

@@ -129,6 +129,7 @@ Singleton {
property var hiddenInputDeviceNames: [] property var hiddenInputDeviceNames: []
property string locale: "" property string locale: ""
property string timeLocale: ""
property string launcherLastMode: "all" property string launcherLastMode: "all"
property string appDrawerLastMode: "apps" property string appDrawerLastMode: "apps"

View File

@@ -80,6 +80,7 @@ var SPEC = {
hiddenInputDeviceNames: { def: [] }, hiddenInputDeviceNames: { def: [] },
locale: { def: "", onChange: "updateLocale" }, locale: { def: "", onChange: "updateLocale" },
timeLocale: { def: "" },
launcherLastMode: { def: "all" }, launcherLastMode: { def: "all" },
appDrawerLastMode: { def: "apps" }, appDrawerLastMode: { def: "apps" },

View File

@@ -1,6 +1,5 @@
import QtQuick import QtQuick
import qs.Common import qs.Common
import qs.Services
import qs.Widgets import qs.Widgets
import qs.Modules.Settings.Widgets import qs.Modules.Settings.Widgets
@@ -9,17 +8,25 @@ Item {
readonly property string _systemDefaultLabel: I18n.tr("System Default") readonly property string _systemDefaultLabel: I18n.tr("System Default")
function capitalizeNativeLanguageName(localeCode) { function _localeDisplayName(localeCode) {
if (I18n.presentLocales[localeCode] == undefined) { if (!I18n.presentLocales[localeCode])
return; return;
}
const nativeName = I18n.presentLocales[localeCode].nativeLanguageName; const nativeName = I18n.presentLocales[localeCode].nativeLanguageName;
return nativeName[0].toUpperCase() + nativeName.slice(1); return nativeName[0].toUpperCase() + nativeName.slice(1);
} }
function _displayValue() { function _allLocaleOptions() {
if (!SessionData.locale) return _systemDefaultLabel; return [_systemDefaultLabel].concat(Object.keys(I18n.presentLocales).map(_localeDisplayName));
return capitalizeNativeLanguageName(SessionData.locale); }
function _codeForDisplayName(displayName) {
if (displayName === _systemDefaultLabel)
return "";
for (const code of Object.keys(I18n.presentLocales)) {
if (_localeDisplayName(code) === displayName)
return code;
}
return "";
} }
DankFlickable { DankFlickable {
@@ -48,24 +55,34 @@ Item {
settingKey: "locale" settingKey: "locale"
text: I18n.tr("Current Locale") text: I18n.tr("Current Locale")
description: I18n.tr("Change the locale used by the DMS interface.") description: I18n.tr("Change the locale used by the DMS interface.")
options: [localeTab._systemDefaultLabel].concat(Object.keys(I18n.presentLocales).map(localeTab.capitalizeNativeLanguageName)) options: localeTab._allLocaleOptions()
enableFuzzySearch: true enableFuzzySearch: true
Component.onCompleted: { Component.onCompleted: {
currentValue = localeTab._displayValue(); currentValue = SessionData.locale ? localeTab._localeDisplayName(SessionData.locale) : localeTab._systemDefaultLabel;
} }
onValueChanged: value => { onValueChanged: value => {
if (value === localeTab._systemDefaultLabel) { SessionData.set("locale", localeTab._codeForDisplayName(value));
SessionData.set("locale", ""); }
return; }
}
for (let code of Object.keys(I18n.presentLocales)) { SettingsDropdownRow {
if (localeTab.capitalizeNativeLanguageName(code) === value) { id: timeLocaleDropdown
SessionData.set("locale", code); tab: "locale"
return; tags: ["locale", "time", "date", "format", "region"]
} settingKey: "timeLocale"
} text: I18n.tr("Time & Date Locale")
description: I18n.tr("Change the locale used for date and time formatting, independent of the interface language.")
options: localeTab._allLocaleOptions()
enableFuzzySearch: true
Component.onCompleted: {
currentValue = SessionData.timeLocale ? localeTab._localeDisplayName(SessionData.timeLocale) : localeTab._systemDefaultLabel;
}
onValueChanged: value => {
SessionData.set("timeLocale", localeTab._codeForDisplayName(value));
} }
} }
} }

View File

@@ -733,6 +733,26 @@
], ],
"icon": "toolbar" "icon": "toolbar"
}, },
{
"section": "barShadowDirectionSource",
"label": "Direction Source",
"tabIndex": 3,
"category": "Dank Bar",
"keywords": [
"bar",
"choose",
"dank",
"direction",
"panel",
"resolves",
"shadow",
"source",
"statusbar",
"taskbar",
"topbar"
],
"description": "Choose how this bar resolves shadow direction"
},
{ {
"section": "barDisplay", "section": "barDisplay",
"label": "Display Assignment", "label": "Display Assignment",
@@ -752,6 +772,25 @@
], ],
"icon": "display_settings" "icon": "display_settings"
}, },
{
"section": "barShadowDirectionManual",
"label": "Manual Direction",
"tabIndex": 3,
"category": "Dank Bar",
"keywords": [
"bar",
"dank",
"direction",
"fixed",
"manual",
"panel",
"shadow",
"statusbar",
"taskbar",
"topbar"
],
"description": "Use a fixed shadow direction for this bar"
},
{ {
"section": "barPosition", "section": "barPosition",
"label": "Position", "label": "Position",
@@ -769,18 +808,23 @@
}, },
{ {
"section": "barShadow", "section": "barShadow",
"label": "Shadow", "label": "Shadow Override",
"tabIndex": 3, "tabIndex": 3,
"category": "Dank Bar", "category": "Dank Bar",
"keywords": [ "keywords": [
"bar", "bar",
"dank", "dank",
"global",
"override",
"panel", "panel",
"settings",
"shadow", "shadow",
"statusbar", "statusbar",
"taskbar",
"topbar" "topbar"
], ],
"icon": "layers" "icon": "layers",
"description": "Override the global shadow with per-bar settings"
}, },
{ {
"section": "barSpacing", "section": "barSpacing",
@@ -2252,6 +2296,33 @@
], ],
"icon": "schedule" "icon": "schedule"
}, },
{
"section": "barElevationEnabled",
"label": "Bar Shadows",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"appearance",
"bar",
"bars",
"colors",
"elevation",
"look",
"m3",
"navigation",
"panel",
"panels",
"scheme",
"shadow",
"shadows",
"statusbar",
"style",
"taskbar",
"theme",
"topbar"
],
"description": "Shadow elevation on bars and panels"
},
{ {
"section": "niriLayoutBorderSize", "section": "niriLayoutBorderSize",
"label": "Border Size", "label": "Border Size",
@@ -2416,74 +2487,6 @@
], ],
"description": "0 = square corners" "description": "0 = square corners"
}, },
{
"section": "m3ElevationEnabled",
"label": "M3 Elevation & Shadows",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"appearance",
"elevation",
"lift",
"material",
"m3",
"shadow",
"shadows",
"theme"
],
"description": "Material Design 3 shadows and elevation on modals, popouts, and dialogs"
},
{
"section": "modalElevationEnabled",
"label": "Modal Shadows",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"dialog",
"elevation",
"m3",
"material",
"modal",
"shadow",
"shadows"
],
"description": "Shadow elevation on modals and dialogs"
},
{
"section": "popoutElevationEnabled",
"label": "Popout Shadows",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"dropdown",
"elevation",
"m3",
"material",
"osd",
"popout",
"popup",
"shadow",
"shadows"
],
"description": "Shadow elevation on popouts, OSDs, and dropdowns"
},
{
"section": "barElevationEnabled",
"label": "Bar Shadows",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"bar",
"elevation",
"m3",
"material",
"navigation",
"panel",
"shadow",
"shadows"
],
"description": "Shadow elevation on bars and panels"
},
{ {
"section": "cursorSize", "section": "cursorSize",
"label": "Cursor Size", "label": "Cursor Size",
@@ -2758,6 +2761,32 @@
"tint" "tint"
] ]
}, },
{
"section": "m3ElevationLightDirection",
"label": "Light Direction",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"advanced",
"appearance",
"cast",
"colors",
"controls",
"day",
"direction",
"elevation",
"layers",
"light",
"light mode",
"look",
"m3",
"scheme",
"shadow",
"style",
"theme"
],
"description": "Controls shadow cast direction for elevation layers"
},
{ {
"section": "isLightMode", "section": "isLightMode",
"label": "Light Mode", "label": "Light Mode",
@@ -2898,6 +2927,29 @@
"icon": "layers", "icon": "layers",
"description": "Show darkened overlay behind modal dialogs" "description": "Show darkened overlay behind modal dialogs"
}, },
{
"section": "modalElevationEnabled",
"label": "Modal Shadows",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"appearance",
"colors",
"dialog",
"dialogs",
"elevation",
"look",
"m3",
"modal",
"modals",
"scheme",
"shadow",
"shadows",
"style",
"theme"
],
"description": "Shadow elevation on modals and dialogs"
},
{ {
"section": "niriLayout", "section": "niriLayout",
"label": "Niri Layout Overrides", "label": "Niri Layout Overrides",
@@ -3158,6 +3210,32 @@
], ],
"description": "Use custom gaps instead of bar spacing" "description": "Use custom gaps instead of bar spacing"
}, },
{
"section": "popoutElevationEnabled",
"label": "Popout Shadows",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"appearance",
"colors",
"dropdown",
"dropdowns",
"elevation",
"look",
"m3",
"osd",
"osds",
"popout",
"popouts",
"popup",
"scheme",
"shadow",
"shadows",
"style",
"theme"
],
"description": "Shadow elevation on popouts, OSDs, and dropdowns"
},
{ {
"section": "popupTransparency", "section": "popupTransparency",
"label": "Popup Transparency", "label": "Popup Transparency",
@@ -3222,6 +3300,105 @@
"user" "user"
] ]
}, },
{
"section": "m3ElevationColorMode",
"label": "Shadow Color",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"appearance",
"applied",
"base",
"color",
"colors",
"colour",
"elevation",
"hue",
"look",
"m3",
"scheme",
"shadow",
"shadows",
"style",
"theme",
"tint"
],
"description": "Base color for shadows (opacity is applied automatically)"
},
{
"section": "m3ElevationIntensity",
"label": "Shadow Intensity",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"appearance",
"base",
"blur",
"colors",
"controls",
"elevation",
"intensity",
"look",
"m3",
"offset",
"radius",
"scheme",
"shadow",
"shadows",
"style",
"theme"
],
"description": "Controls the base blur radius and offset of shadows"
},
{
"section": "m3ElevationOpacity",
"label": "Shadow Opacity",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"alpha",
"appearance",
"colors",
"controls",
"elevation",
"look",
"m3",
"opacity",
"scheme",
"shadow",
"style",
"theme",
"translucent",
"transparency",
"transparent"
],
"description": "Controls the transparency of the shadow"
},
{
"section": "m3ElevationEnabled",
"label": "Shadows",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"appearance",
"colors",
"dialogs",
"elevation",
"inspired",
"lift",
"look",
"m3",
"material",
"modals",
"popouts",
"scheme",
"shadow",
"shadows",
"style",
"theme"
],
"description": "Material inspired shadows and elevation on modals, popouts, and dialogs"
},
{ {
"section": "syncModeWithPortal", "section": "syncModeWithPortal",
"label": "Sync Mode with Portal", "label": "Sync Mode with Portal",
@@ -4038,27 +4215,6 @@
], ],
"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",
@@ -5358,20 +5514,33 @@
"keywords": [ "keywords": [
"alert", "alert",
"alerts", "alerts",
"appearance",
"colors",
"colour",
"colours",
"drop", "drop",
"elevation",
"enabled",
"hue",
"look",
"messages", "messages",
"notif", "notif",
"notification", "notification",
"notifications", "notifications",
"palette",
"popup", "popup",
"popups", "popups",
"radius", "radius",
"requires",
"rounded", "rounded",
"shadow", "shadow",
"show", "show",
"style",
"theme",
"tint",
"toast" "toast"
], ],
"description": "Show drop shadow on notification popups" "description": "Show drop shadow on notification popups. Requires M3 Elevation to be enabled in Theme & Colors."
}, },
{ {
"section": "notificationPopupPrivacyMode", "section": "notificationPopupPrivacyMode",
@@ -6023,6 +6192,27 @@
"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",
@@ -6618,5 +6808,25 @@
], ],
"icon": "language", "icon": "language",
"description": "Change the locale used by the DMS interface." "description": "Change the locale used by the DMS interface."
},
{
"section": "timeLocale",
"label": "Time & Date Locale",
"tabIndex": 30,
"category": "Locale",
"keywords": [
"change",
"country",
"date",
"format",
"formatting",
"independent",
"interface",
"language",
"locale",
"region",
"time"
],
"description": "Change the locale used for date and time formatting, independent of the interface language."
} }
] ]