i18n: allow user prefered locale over browser preference and vice versa

This commit is contained in:
axolotle 2023-11-25 20:14:12 +01:00
parent 44744e31a5
commit 5c51df52c0
5 changed files with 77 additions and 14 deletions

View file

@ -1,3 +1,5 @@
// AUTH
export const useIsLoggedIn = () => {
const isLoggedIn = useState<boolean>(
'isLoggedIn',
@ -13,6 +15,34 @@ export const useIsLoggedIn = () => {
})
}
// LOCALE
const usePreferedLocaleState = () =>
useState<string>(
'preferedLocale',
() => localStorage.getItem('preferedLocale') || 'auto',
)
export const usePreferedLocale = () => {
const preferedLocale = usePreferedLocaleState()
const { locale, getBrowserLocale, defaultLocale } = useNuxtApp().$i18n
return computed({
get: () => preferedLocale.value,
set: (value) => {
preferedLocale.value = value
localStorage.setItem('preferedLocale', value)
if (value === 'auto') {
const browserLocale = getBrowserLocale()
value = browserLocale || defaultLocale
}
locale.value = value
},
})
}
export const useRedirectUrl = () =>
useState<string | null>('redirectUrl', () => null)

View file

@ -11,6 +11,7 @@
"processing": "Processing…"
},
"app_list": "App list",
"automatic": "Automatic ({name})",
"back_to_apps": "Go back to app list",
"cancel": "Cancel",
"change_password": "Change password",

View file

@ -40,6 +40,9 @@ export default defineNuxtConfig({
lazy: true,
langDir: 'locales',
locales: locales as LocaleObject[],
detectBrowserLanguage: {
useCookie: false,
},
},
colorMode: {
preference: 'system',

View file

@ -1,15 +1,27 @@
<script setup lang="ts">
const { t, locale, locales } = useI18n()
const { t, locales, getBrowserLocale } = useI18n()
useHead({
title: t('footerlink_edit'),
})
const preferedLocale = usePreferedLocale()
const localesAsOptions = computed(() => {
return locales.value.map((locale) => ({
const options = locales.value.map((locale) => ({
text: locale.name,
value: locale.code,
}))
const browserLocale = getBrowserLocale()
const browserLocaleName = locales.value.find(
(locale) => locale.code === browserLocale,
)?.name
options.unshift({
text: t('automatic', { name: browserLocaleName }),
value: 'auto',
})
return options
})
const colorMode = useColorMode()
@ -80,7 +92,11 @@ const themesAsOptions = [
<div role="group" class="flex align mb-3">
<!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
<label for="language" class="label me-3">{{ t('language') }}</label>
<select id="language" v-model="locale" class="select select-bordered">
<select
id="language"
v-model="preferedLocale"
class="select select-bordered"
>
<option disabled selected>{{ t('language') }}</option>
<option
v-for="option in localesAsOptions"

View file

@ -1,15 +1,28 @@
import { setLocale } from 'yup'
import { usePreferedLocale } from '@/composables/states'
export default defineNuxtPlugin(() => {
// https://github.com/jquense/yup/blob/master/src/locale.ts
setLocale({
mixed: {
default: 'v.field_invalid',
required: 'v.field_required',
export default defineNuxtPlugin({
setup() {
// Override default yup errors
// https://github.com/jquense/yup/blob/master/src/locale.ts
setLocale({
mixed: {
default: 'v.field_invalid',
required: 'v.field_required',
},
string: {
email: 'v.email',
min: ({ min }) => ({ key: 'v.string_too_short', values: { min } }),
},
})
},
hooks: {
'app:created'() {
// Override browser locale if prefered language
const preferedLocale = usePreferedLocale()
if (preferedLocale.value !== 'auto') {
useNuxtApp().$i18n.locale.value = preferedLocale.value
}
},
string: {
email: 'v.email',
min: ({ min }) => ({ key: 'v.string_too_short', values: { min } }),
},
})
},
})