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:
@@ -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 = ({});
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"),
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
63
quickshell/Modules/Settings/LocaleTab.qml
Normal file
63
quickshell/Modules/Settings/LocaleTab.qml
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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
@@ -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 = [
|
||||||
|
|||||||
@@ -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."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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": "",
|
||||||
|
|||||||
Reference in New Issue
Block a user