diff --git a/composables/settings/definition.ts b/composables/settings/definition.ts index 4f66e9a7..131bf986 100644 --- a/composables/settings/definition.ts +++ b/composables/settings/definition.ts @@ -1,4 +1,4 @@ -import { DEFAULT_FONT_SIZE, DEFAULT_LANGUAGE } from '~/constants' +import { DEFAULT_FONT_SIZE } from '~/constants' export type FontSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' export type ColorMode = 'light' | 'dark' | 'system' @@ -24,9 +24,15 @@ export interface UserSettings { zenMode: boolean } -export function getDefaultUserSettings(): UserSettings { +export function getDefaultLanguage(languages: string[]) { + if (process.server) + return 'en-US' + return matchLanguages(languages, navigator.languages) || 'en-US' +} + +export function getDefaultUserSettings(locales: string[]): UserSettings { return { - language: DEFAULT_LANGUAGE, + language: getDefaultLanguage(locales), fontSize: DEFAULT_FONT_SIZE, zenMode: false, featureFlags: {}, diff --git a/composables/settings/storage.ts b/composables/settings/storage.ts index 6c0395c5..ae0ad0ed 100644 --- a/composables/settings/storage.ts +++ b/composables/settings/storage.ts @@ -1,9 +1,14 @@ import type { Ref } from 'vue' +import type { VueI18n } from 'vue-i18n' +import type { LocaleObject } from 'vue-i18n-routing' import type { FeatureFlags, UserSettings, WellnessSettings } from './definition' import { STORAGE_KEY_SETTINGS } from '~/constants' export function useUserSettings() { - return useUserLocalStorage(STORAGE_KEY_SETTINGS, getDefaultUserSettings) + const i18n = useNuxtApp().vueApp.config.globalProperties.$i18n as VueI18n + const { locales } = i18n + const supportLanguages = (locales as LocaleObject[]).map(locale => locale.code) + return useUserLocalStorage(STORAGE_KEY_SETTINGS, () => getDefaultUserSettings(supportLanguages)) } // TODO: refactor & simplify this diff --git a/constants/index.ts b/constants/index.ts index f3552c65..e1d3f8ab 100644 --- a/constants/index.ts +++ b/constants/index.ts @@ -2,7 +2,6 @@ export const APP_NAME = 'Elk' export const DEFAULT_POST_CHARS_LIMIT = 500 export const DEFAULT_FONT_SIZE = 'md' -export const DEFAULT_LANGUAGE = 'en-US' export const STORAGE_KEY_DRAFTS = 'elk-drafts' export const STORAGE_KEY_USERS = 'elk-users' diff --git a/plugins/setup-i18n.ts b/plugins/setup-i18n.ts index cdd4b647..3ea23f27 100644 --- a/plugins/setup-i18n.ts +++ b/plugins/setup-i18n.ts @@ -1,39 +1,22 @@ import type { VueI18n } from 'vue-i18n' import type { LocaleObject } from 'vue-i18n-routing' -import { DEFAULT_LANGUAGE } from '~/constants' export default defineNuxtPlugin(async (nuxt) => { const i18n = nuxt.vueApp.config.globalProperties.$i18n as VueI18n const { setLocale, locales } = i18n const supportLanguages = (locales as LocaleObject[]).map(locale => locale.code) const userSettings = useUserSettings() + const lang = userSettings.value.language + + if (process.client && !supportLanguages.includes(lang)) + userSettings.value.language = getDefaultLanguage(locales as string[]) if (process.server) { - const headers = useRequestHeaders() - - let lang = userSettings.value.language - if (!lang || !supportLanguages.includes(lang)) { - // first visit - if (headers['accept-language']) { - // detect language from header - const userLanguages = headers['accept-language'].split(',').map(lang => lang.split(';')[0].toLowerCase()) - lang = matchLanguages(supportLanguages, userLanguages) || DEFAULT_LANGUAGE - } - else { - lang = DEFAULT_LANGUAGE - } - } - if (lang !== i18n.locale) - await setLocale(userSettings.value.language) - + await setLocale(lang) return } - // could be null if browser don't accept cookie - if (!userSettings.value.language || !supportLanguages.includes(userSettings.value.language)) - userSettings.value.language = DEFAULT_LANGUAGE - watch(() => userSettings.value.language, (lang) => { if (lang !== i18n.locale) setLocale(lang) diff --git a/utils/language.ts b/utils/language.ts index ab53882a..1b41d715 100644 --- a/utils/language.ts +++ b/utils/language.ts @@ -1,4 +1,4 @@ -export function matchLanguages(languages: string[], acceptLanguages: string[]): string | null { +export function matchLanguages(languages: string[], acceptLanguages: readonly string[]): string | null { { const lang = acceptLanguages.map(userLang => languages.find(lang => lang.startsWith(userLang))).filter(v => !!v)[0] if (lang)