From bb36a46a24201358a9b4fceb8ac758a5455c2e09 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Thu, 22 Jan 2026 00:12:22 +0100 Subject: [PATCH] Save selected app language on server --- CHANGELOG.md | 1 + src/features/metadata/Metadata.constants.ts | 15 +++++++++++++++ src/features/settings/Settings.constants.ts | 2 ++ src/features/settings/screens/Appearance.tsx | 19 +++++++++++-------- src/features/theme/AppTheme.types.ts | 1 + src/features/theme/AppThemeContext.tsx | 16 +++++++++++++--- src/i18n/index.ts | 20 +------------------- src/i18n/locales/en.po | 4 ++++ src/lib/ISOLanguageUtil.ts | 10 ++++++++++ 9 files changed, 58 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be35b3d8..79fe0a34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Changed - (**General**) Preserve refresh token (UI Login) over sessions - (**General**) Reduce base font size +- (**General**) Save selected app language on the server - (**Theme**) Improve automatic theme background colors - (**Theme**) Adjust "primary color" of dynamic color theme on manga pages - (**Theme**) Increase max length of custom theme names to 32 (previously 16) diff --git a/src/features/metadata/Metadata.constants.ts b/src/features/metadata/Metadata.constants.ts index b34de631..e3d93ad9 100644 --- a/src/features/metadata/Metadata.constants.ts +++ b/src/features/metadata/Metadata.constants.ts @@ -33,6 +33,8 @@ import { ISourceMetadata } from '@/features/source/Source.types.ts'; import { LibraryOptions } from '@/features/library/Library.types.ts'; import { MetadataThemeSettings } from '@/features/theme/AppTheme.types.ts'; import { TapZoneInvertMode } from '@/features/reader/tap-zones/TapZoneLayout.types.ts'; +import { detectLocale, getISOLanguage } from '@/lib/ISOLanguageUtil.ts'; +import { i18nResources } from '@/i18n'; export const APP_METADATA_KEY_PREFIX = 'webUI'; @@ -374,6 +376,18 @@ export const APP_METADATA: Record< excludedScanlators: { convert: convertToObject, }, + locale: { + convert: convertToString, + toConstrainedValue: (value: string) => { + const locale = getISOLanguage(value)?.isoCode; + + if (!locale || !i18nResources.includes(locale)) { + return detectLocale(); + } + + return locale; + }, + }, } as const; export const VALID_APP_METADATA_KEYS = Object.keys(APP_METADATA); @@ -446,6 +460,7 @@ export const GLOBAL_METADATA_KEYS: AppMetadataKeys[] = [ 'isEnabled', // themes + 'locale', 'customThemes', 'mangaThumbnailBackdrop', 'mangaDynamicColorSchemes', diff --git a/src/features/settings/Settings.constants.ts b/src/features/settings/Settings.constants.ts index deb05d10..cacde961 100644 --- a/src/features/settings/Settings.constants.ts +++ b/src/features/settings/Settings.constants.ts @@ -30,6 +30,7 @@ import { WebUiInterface, } from '@/lib/graphql/generated/graphql.ts'; import { ThemeMode } from '@/features/theme/AppTheme.types.ts'; +import { getPreferredISOLanguageCodes } from '@/lib/ISOLanguageUtil.ts'; export const MANGA_GRID_WIDTH = { min: 100, @@ -85,6 +86,7 @@ export const SERVER_SETTINGS_METADATA_DEFAULT: MetadataServerSettings = { serverInformAvailableUpdate: true, // themes + locale: getPreferredISOLanguageCodes()[0], appTheme: 'default', themeMode: ThemeMode.SYSTEM, shouldUsePureBlackMode: false, diff --git a/src/features/settings/screens/Appearance.tsx b/src/features/settings/screens/Appearance.tsx index fc2bcea8..85fe2410 100644 --- a/src/features/settings/screens/Appearance.tsx +++ b/src/features/settings/screens/Appearance.tsx @@ -19,7 +19,7 @@ import { useAppThemeContext } from '@/features/theme/AppThemeContext.tsx'; import { Select } from '@/base/components/inputs/Select.tsx'; import { MediaQuery } from '@/base/utils/MediaQuery.tsx'; import { NumberSetting } from '@/base/components/settings/NumberSetting.tsx'; -import { I18nResourceCode, i18nResources, loadCatalog } from '@/i18n'; +import { i18nResources, loadCatalog } from '@/i18n'; import { languageCodeToName } from '@/base/utils/Languages.ts'; import { ThemeList } from '@/features/theme/components/ThemeList.tsx'; import { @@ -38,7 +38,7 @@ import { MANGA_GRID_WIDTH, SERVER_SETTINGS_METADATA_DEFAULT } from '@/features/s import { MUI_THEME_MODE_KEY } from '@/lib/mui/MUI.constants.ts'; export const Appearance = () => { - const { t, i18n } = useLingui(); + const { t } = useLingui(); const { themeMode, setThemeMode, shouldUsePureBlackMode, setShouldUsePureBlackMode } = useAppThemeContext(); const { mode, setMode } = useColorScheme(); const actualThemeMode = (mode ?? themeMode) as ThemeMode; @@ -46,7 +46,7 @@ export const Appearance = () => { useAppTitle(t`Appearance`); const { - settings: { mangaThumbnailBackdrop, mangaDynamicColorSchemes, mangaGridItemWidth }, + settings: { mangaThumbnailBackdrop, mangaDynamicColorSchemes, mangaGridItemWidth, locale }, request: { loading, error, refetch }, } = useMetadataServerSettings(); const updateMetadataSetting = createUpdateMetadataServerSettings((e) => @@ -135,12 +135,15 @@ export const Appearance = () => { } />