diff --git a/web/src/lib/constants.ts b/web/src/lib/constants.ts index b86e057ffd10b..f098d398f2dba 100644 --- a/web/src/lib/constants.ts +++ b/web/src/lib/constants.ts @@ -327,6 +327,12 @@ export const langs = [ { name: 'Development (keys only)', code: 'dev', loader: () => Promise.resolve({}) }, ]; +// browser is zh-CN, but weblate use zh-Hans +export const langAliasesMap: { [key: string]: string } = { + 'zh-CN' : 'zh-Hans', + 'zh-TW' : 'zh-Hant' +}; + export enum ImmichProduct { Client = 'immich-client', Server = 'immich-server', diff --git a/web/src/lib/i18n.spec.ts b/web/src/lib/i18n.spec.ts index 13d926e6473f3..ffe64cc7cae1f 100644 --- a/web/src/lib/i18n.spec.ts +++ b/web/src/lib/i18n.spec.ts @@ -24,7 +24,7 @@ describe('i18n', () => { }); describe('getClosestAvailableLocale', () => { - const allLocales = ['ar', 'bg', 'en', 'en-US', 'en-DE', 'zh-Hans', 'zh-Hans-HK']; + const allLocales = ['ar', 'bg', 'en', 'en-US', 'en-DE', 'zh-Hans', 'zh-Hans-HK', 'zh-HK', 'zh-Hant']; it('returns undefined on mismatch', () => { expect(getClosestAvailableLocale([], allLocales)).toBeUndefined(); @@ -47,5 +47,11 @@ describe('i18n', () => { expect(getClosestAvailableLocale(['zh'], allLocales)).toBeUndefined(); expect(getClosestAvailableLocale(['de', 'zh', 'en-US'], allLocales)).toBe('en-US'); }); + + it('returns the locale for a alias match', () => { + expect(getClosestAvailableLocale(['zh-CN'], allLocales)).toBe('zh-Hans'); + expect(getClosestAvailableLocale(['zh-TW'], allLocales)).toBe('zh-Hant'); + }); + }); }); diff --git a/web/src/lib/utils/i18n.ts b/web/src/lib/utils/i18n.ts index 83fe11875cc07..a2ea431bae298 100644 --- a/web/src/lib/utils/i18n.ts +++ b/web/src/lib/utils/i18n.ts @@ -1,4 +1,4 @@ -import { langs } from '$lib/constants'; +import { langAliasesMap, langs } from '$lib/constants'; import { locale, t, waitLocale } from 'svelte-i18n'; import { get, type Unsubscriber } from 'svelte/store'; @@ -23,7 +23,8 @@ function getSubLocales(refLocale: string) { export function getClosestAvailableLocale(locales: readonly string[], allLocales: readonly string[]) { const allLocalesSet = new Set(allLocales); - return locales.find((locale) => getSubLocales(locale).some((subLocale) => allLocalesSet.has(subLocale))); + const expandedLocales = locales.flatMap((locale) => [locale, langAliasesMap[locale] ?? null]).filter(Boolean); + return expandedLocales.find((locale) => getSubLocales(locale).some((subLocale) => allLocalesSet.has(subLocale))); } export const langCodes = langs.map((lang) => lang.code);