themeManager.setTheme(theme == 'dark' ? Theme.DARK : Theme.LIGHT)}
+ />
+ {/await}
{/if}
diff --git a/web/src/lib/components/user-settings-page/app-settings.svelte b/web/src/lib/components/user-settings-page/app-settings.svelte
index adb37d5d939..d248038a240 100644
--- a/web/src/lib/components/user-settings-page/app-settings.svelte
+++ b/web/src/lib/components/user-settings-page/app-settings.svelte
@@ -39,7 +39,7 @@
};
const handleToggleLocaleBrowser = () => {
- $locale = $locale ? undefined : fallbackLocale.code;
+ $locale = $locale === 'default' ? fallbackLocale.code : 'default';
};
const handleLocaleChange = (newLocale: string | undefined) => {
@@ -89,13 +89,13 @@
{selectedDate}
- {#if $locale !== undefined}
+ {#if $locale !== 'default'}
($alwaysLoadOriginalFile = !$alwaysLoadOriginalFile)}
/>
@@ -121,16 +120,10 @@
title={$t('video_hover_setting')}
subtitle={$t('video_hover_setting_description')}
bind:checked={$playVideoThumbnailOnHover}
- onToggle={() => ($playVideoThumbnailOnHover = !$playVideoThumbnailOnHover)}
/>
- ($loopVideo = !$loopVideo)}
- />
+
diff --git a/web/src/lib/constants.ts b/web/src/lib/constants.ts
index fdb18b39781..ae53b4e7f3f 100644
--- a/web/src/lib/constants.ts
+++ b/web/src/lib/constants.ts
@@ -273,9 +273,17 @@ export const locales = [
{ code: 'zu-ZA', name: 'Zulu (South Africa)' },
];
-export const defaultLang = { name: 'English', code: 'en', loader: () => import('$i18n/en.json') };
+interface Lang {
+ name: string;
+ code: string;
+ loader: () => Promise<{ default: object }>;
+ rtl?: boolean;
+ weblateCode?: string;
+}
-export const langs = [
+export const defaultLang: Lang = { name: 'English', code: 'en', loader: () => import('$i18n/en.json') };
+
+export const langs: Lang[] = [
{ name: 'Afrikaans', code: 'af', loader: () => import('$i18n/af.json') },
{ name: 'Arabic', code: 'ar', loader: () => import('$i18n/ar.json'), rtl: true },
{ name: 'Azerbaijani', code: 'az', loader: () => import('$i18n/az.json'), rtl: true },
@@ -359,7 +367,7 @@ export const langs = [
weblateCode: 'zh_SIMPLIFIED',
loader: () => import('$i18n/zh_SIMPLIFIED.json'),
},
- { name: 'Development (keys only)', code: 'dev', loader: () => Promise.resolve({}) },
+ { name: 'Development (keys only)', code: 'dev', loader: () => Promise.resolve({ default: {} }) },
];
export enum ImmichProduct {
diff --git a/web/src/lib/stores/preferences.store.ts b/web/src/lib/stores/preferences.store.ts
index e7f38eb6d08..f0689e5d6e6 100644
--- a/web/src/lib/stores/preferences.store.ts
+++ b/web/src/lib/stores/preferences.store.ts
@@ -9,9 +9,9 @@ export interface ThemeSetting {
}
// Locale to use for formatting dates, numbers, etc.
-export const locale = persisted('locale', undefined, {
+export const locale = persisted('locale', 'default', {
serializer: {
- parse: (text) => (text == '' ? 'en-US' : text),
+ parse: (text) => text || 'default',
stringify: (object) => object ?? '',
},
});
diff --git a/web/src/lib/utils/timeline-util.spec.ts b/web/src/lib/utils/timeline-util.spec.ts
index f842b948e06..c77aefc0b49 100644
--- a/web/src/lib/utils/timeline-util.spec.ts
+++ b/web/src/lib/utils/timeline-util.spec.ts
@@ -1,3 +1,4 @@
+import { locale } from '$lib/stores/preferences.store';
import { parseUtcDate } from '$lib/utils/date-time';
import { formatGroupTitle } from '$lib/utils/timeline-util';
import { DateTime } from 'luxon';
@@ -16,48 +17,63 @@ describe('formatGroupTitle', () => {
it('formats today', () => {
const date = parseUtcDate('2024-07-27T01:00:00Z');
- expect(formatGroupTitle(date.setLocale('en'))).toBe('today');
- expect(formatGroupTitle(date.setLocale('es'))).toBe('hoy');
+ locale.set('en');
+ expect(formatGroupTitle(date)).toBe('today');
+ locale.set('es');
+ expect(formatGroupTitle(date)).toBe('hoy');
});
it('formats yesterday', () => {
const date = parseUtcDate('2024-07-26T23:59:59Z');
- expect(formatGroupTitle(date.setLocale('en'))).toBe('yesterday');
- expect(formatGroupTitle(date.setLocale('fr'))).toBe('hier');
+ locale.set('en');
+ expect(formatGroupTitle(date)).toBe('yesterday');
+ locale.set('fr');
+ expect(formatGroupTitle(date)).toBe('hier');
});
it('formats last week', () => {
const date = parseUtcDate('2024-07-21T00:00:00Z');
- expect(formatGroupTitle(date.setLocale('en'))).toBe('Sunday');
- expect(formatGroupTitle(date.setLocale('ar-SA'))).toBe('الأحد');
+ locale.set('en');
+ expect(formatGroupTitle(date)).toBe('Sunday');
+ locale.set('ar-SA');
+ expect(formatGroupTitle(date)).toBe('الأحد');
});
it('formats date 7 days ago', () => {
const date = parseUtcDate('2024-07-20T00:00:00Z');
- expect(formatGroupTitle(date.setLocale('en'))).toBe('Sat, Jul 20');
- expect(formatGroupTitle(date.setLocale('de'))).toBe('Sa., 20. Juli');
+ locale.set('en');
+ expect(formatGroupTitle(date)).toBe('Sat, Jul 20');
+ locale.set('de');
+ expect(formatGroupTitle(date)).toBe('Sa., 20. Juli');
});
it('formats date this year', () => {
const date = parseUtcDate('2020-01-01T00:00:00Z');
- expect(formatGroupTitle(date.setLocale('en'))).toBe('Wed, Jan 1, 2020');
- expect(formatGroupTitle(date.setLocale('ja'))).toBe('2020年1月1日(水)');
+ locale.set('en');
+ expect(formatGroupTitle(date)).toBe('Wed, Jan 1, 2020');
+ locale.set('ja');
+ expect(formatGroupTitle(date)).toBe('2020年1月1日(水)');
});
it('formats future date', () => {
const tomorrow = parseUtcDate('2024-07-28T00:00:00Z');
- expect(formatGroupTitle(tomorrow.setLocale('en'))).toBe('Sun, Jul 28');
+ locale.set('en');
+ expect(formatGroupTitle(tomorrow)).toBe('Sun, Jul 28');
const nextMonth = parseUtcDate('2024-08-28T00:00:00Z');
- expect(formatGroupTitle(nextMonth.setLocale('en'))).toBe('Wed, Aug 28');
+ locale.set('en');
+ expect(formatGroupTitle(nextMonth)).toBe('Wed, Aug 28');
const nextYear = parseUtcDate('2025-01-10T12:00:00Z');
- expect(formatGroupTitle(nextYear.setLocale('en'))).toBe('Fri, Jan 10, 2025');
+ locale.set('en');
+ expect(formatGroupTitle(nextYear)).toBe('Fri, Jan 10, 2025');
});
it('returns "Invalid DateTime" when date is invalid', () => {
const date = DateTime.invalid('test');
- expect(formatGroupTitle(date.setLocale('en'))).toBe('Invalid DateTime');
- expect(formatGroupTitle(date.setLocale('es'))).toBe('Invalid DateTime');
+ locale.set('en');
+ expect(formatGroupTitle(date)).toBe('Invalid DateTime');
+ locale.set('es');
+ expect(formatGroupTitle(date)).toBe('Invalid DateTime');
});
});
diff --git a/web/src/lib/utils/timeline-util.ts b/web/src/lib/utils/timeline-util.ts
index d8252271a22..7538e0e02c1 100644
--- a/web/src/lib/utils/timeline-util.ts
+++ b/web/src/lib/utils/timeline-util.ts
@@ -62,12 +62,12 @@ export function formatGroupTitle(_date: DateTime): string {
// Today
if (today.hasSame(date, 'day')) {
- return date.toRelativeCalendar();
+ return date.toRelativeCalendar({ locale: get(locale) });
}
// Yesterday
if (today.minus({ days: 1 }).hasSame(date, 'day')) {
- return date.toRelativeCalendar();
+ return date.toRelativeCalendar({ locale: get(locale) });
}
// Last week