From 3dd9eded41edf897c5276fbf3436ab482f0405a0 Mon Sep 17 00:00:00 2001 From: Jakob Scheid Date: Thu, 6 Aug 2026 23:52:29 +0200 Subject: [PATCH 1/8] feature(settings)!: make settings configuration a JavaScript module The settings configuration is now a JavaScript module because dynamic configuration is only possible in this way and dynamic settings configuration is needed for the language as a setting. --- .../composables/__tests__/useSettings.test.js | 2 +- .../settings/composables/useSettings.js | 2 +- src/features/settings/config.js | 46 +++++++++++++++++++ src/features/settings/settings.json | 30 ------------ src/features/settings/views/SettingsView.vue | 2 +- .../views/__tests__/SettingsView.test.js | 2 +- src/main.js | 2 +- 7 files changed, 51 insertions(+), 35 deletions(-) create mode 100644 src/features/settings/config.js delete mode 100644 src/features/settings/settings.json diff --git a/src/features/settings/composables/__tests__/useSettings.test.js b/src/features/settings/composables/__tests__/useSettings.test.js index aec200d..5bbda77 100644 --- a/src/features/settings/composables/__tests__/useSettings.test.js +++ b/src/features/settings/composables/__tests__/useSettings.test.js @@ -22,7 +22,7 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; const settingDefaultValue = vi.hoisted(() => 42); const settingPath = ['test', 'number']; -vi.mock('../../settings.json', () => ({ +vi.mock('../../config.js', () => ({ default: { contents: [ { diff --git a/src/features/settings/composables/useSettings.js b/src/features/settings/composables/useSettings.js index 8c469a6..c42ef99 100644 --- a/src/features/settings/composables/useSettings.js +++ b/src/features/settings/composables/useSettings.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import settings from '../settings.json'; +import settings from '../config.js'; import { useSettingsStore } from '../stores/settingsStore'; import { getSettingRecursively } from '../utils/getSetting'; diff --git a/src/features/settings/config.js b/src/features/settings/config.js new file mode 100644 index 0000000..cebce17 --- /dev/null +++ b/src/features/settings/config.js @@ -0,0 +1,46 @@ +/* +Copyright 2026 Seekra + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export default { + contents: [ + { + name: 'appearance', + i18n: 'settings.settings.appearance.title', + content: [ + { + name: 'colorScheme', + type: 'selection', + i18n: 'settings.settings.appearance.contents.colorScheme.title', + default: 'auto', + options: [ + { + name: 'auto', + i18n: 'settings.settings.appearance.contents.colorScheme.options.auto' + }, + { + name: 'light', + i18n: 'settings.settings.appearance.contents.colorScheme.options.light' + }, + { + name: 'dark', + i18n: 'settings.settings.appearance.contents.colorScheme.options.dark' + } + ] + } + ] + } + ] +}; diff --git a/src/features/settings/settings.json b/src/features/settings/settings.json deleted file mode 100644 index 76a4f69..0000000 --- a/src/features/settings/settings.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "contents": [ - { - "name": "appearance", - "i18n": "settings.settings.appearance.title", - "content": [ - { - "name": "colorScheme", - "type": "selection", - "i18n": "settings.settings.appearance.contents.colorScheme.title", - "default": "auto", - "options": [ - { - "name": "auto", - "i18n": "settings.settings.appearance.contents.colorScheme.options.auto" - }, - { - "name": "light", - "i18n": "settings.settings.appearance.contents.colorScheme.options.light" - }, - { - "name": "dark", - "i18n": "settings.settings.appearance.contents.colorScheme.options.dark" - } - ] - } - ] - } - ] -} diff --git a/src/features/settings/views/SettingsView.vue b/src/features/settings/views/SettingsView.vue index d241ee9..538dfc2 100644 --- a/src/features/settings/views/SettingsView.vue +++ b/src/features/settings/views/SettingsView.vue @@ -18,7 +18,7 @@ limitations under the License. import LeftSidebarLayout from '@/layouts/LeftSidebarLayout.vue'; import SettingsPage from '../components/SettingsPage.vue'; -import settingsConfiguration from '../settings.json'; +import settingsConfiguration from '../config.js'; import { getSettingRecursively } from '../utils/getSetting.js'; import { computed, onMounted, ref, watch } from 'vue'; import { useI18n } from 'vue-i18n'; diff --git a/src/features/settings/views/__tests__/SettingsView.test.js b/src/features/settings/views/__tests__/SettingsView.test.js index 446f3a1..4a49a6f 100644 --- a/src/features/settings/views/__tests__/SettingsView.test.js +++ b/src/features/settings/views/__tests__/SettingsView.test.js @@ -197,7 +197,7 @@ const settings = settingsHoisted.values(); const originalCurrentSection = 's0'; let currentSection = originalCurrentSection; -vi.mock('../../settings.json', () => ({ +vi.mock('../../config.js', () => ({ default: { contents: settingsHoisted } })); diff --git a/src/main.js b/src/main.js index d7efce6..1b54fcb 100644 --- a/src/main.js +++ b/src/main.js @@ -30,7 +30,7 @@ import rawFonts from './styles/fonts.json'; import './styles/common.css'; import './styles/variables/colors.css'; -import settings from './features/settings/settings.json'; +import settings from './features/settings/config.js'; import { validateSettingsConfig } from './features/settings/utils/settingsValidator'; (async () => { From d5f6108f4761272d9bfe4dca3a7c804fec894965 Mon Sep 17 00:00:00 2001 From: Jakob Scheid Date: Thu, 6 Aug 2026 23:59:10 +0200 Subject: [PATCH 2/8] feat(i18n): add language settings --- src/config/featureSettings.js | 17 +++++++++++++++++ src/features/settings/config.js | 18 ++++++++++++++++++ src/locales/de.json | 8 ++++++++ src/locales/en.json | 8 ++++++++ 4 files changed, 51 insertions(+) create mode 100644 src/config/featureSettings.js diff --git a/src/config/featureSettings.js b/src/config/featureSettings.js new file mode 100644 index 0000000..6138028 --- /dev/null +++ b/src/config/featureSettings.js @@ -0,0 +1,17 @@ +/* +Copyright 2026 Seekra + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export const LANGUAGE_PATH = ['general', 'language']; diff --git a/src/features/settings/config.js b/src/features/settings/config.js index cebce17..a72d7e0 100644 --- a/src/features/settings/config.js +++ b/src/features/settings/config.js @@ -14,8 +14,26 @@ See the License for the specific language governing permissions and limitations under the License. */ +import { fallbackLocale, SUPPORTED_LANGUAGES } from '@/i18n'; + export default { contents: [ + { + name: 'general', + i18n: 'settings.settings.general.title', + content: [ + { + name: 'language', + type: 'selection', + i18n: 'settings.settings.general.settings.language.title', + default: fallbackLocale, + options: SUPPORTED_LANGUAGES.map((language) => ({ + name: language, + i18n: `preferences.locale.languages.${language}` + })) + } + ] + }, { name: 'appearance', i18n: 'settings.settings.appearance.title', diff --git a/src/locales/de.json b/src/locales/de.json index 53e537a..64eb789 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -74,6 +74,14 @@ } } } + }, + "general": { + "title": "Allgemein", + "settings": { + "language": { + "title": "Sprache" + } + } } } }, diff --git a/src/locales/en.json b/src/locales/en.json index 158b349..facfb20 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -74,6 +74,14 @@ } } } + }, + "general": { + "title": "General", + "settings": { + "language": { + "title": "Language" + } + } } } }, From b571a68e3b8589631f8f104dd12c60f1984522aa Mon Sep 17 00:00:00 2001 From: Jakob Scheid Date: Fri, 7 Aug 2026 00:28:25 +0200 Subject: [PATCH 3/8] feat(i18n): use settings to set and get language --- src/App.vue | 4 ++ .../i18n/components/LanguageSwitchButton.vue | 12 ++-- .../__tests__/LanguageSwitchButton.test.js | 69 ++++++------------- src/i18n.js | 8 ++- 4 files changed, 38 insertions(+), 55 deletions(-) diff --git a/src/App.vue b/src/App.vue index c6d080c..193c169 100644 --- a/src/App.vue +++ b/src/App.vue @@ -18,8 +18,10 @@ limitations under the License. import Navbar from './features/nav/components/Navbar.vue'; import Footer from './features/footer/components/Footer.vue'; +import { LANGUAGE_PATH } from './config/featureSettings.js'; import { updatePageTitle } from './router'; import { useSettings } from './features/settings/composables/useSettings.js'; +import { setLocale } from './i18n'; import { computed, watch, watchEffect } from 'vue'; import { useRoute } from 'vue-router'; @@ -51,6 +53,8 @@ watch(colorScheme, (newColorScheme) => { updateColorScheme(colorScheme.value); watchEffect(() => updatePageTitle(route)); + +watch(() => getSetting(LANGUAGE_PATH), setLocale);