fix: i18n SSR
parent
d09b4deb52
commit
970b6538e2
5
app.vue
5
app.vue
|
@ -1,13 +1,12 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
setupI18n()
|
|
||||||
setupPageHeader()
|
setupPageHeader()
|
||||||
setupEmojis()
|
setupEmojis()
|
||||||
provideGlobalCommands()
|
provideGlobalCommands()
|
||||||
|
|
||||||
|
await setupI18n()
|
||||||
|
|
||||||
// We want to trigger rerendering the page when account changes
|
// We want to trigger rerendering the page when account changes
|
||||||
const key = computed(() => `${currentUser.value?.server ?? currentServer.value}:${currentUser.value?.account.id || ''}`)
|
const key = computed(() => `${currentUser.value?.server ?? currentServer.value}:${currentUser.value?.account.id || ''}`)
|
||||||
|
|
||||||
const { params } = useRoute()
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { pwaInfo } from 'virtual:pwa-info'
|
import { pwaInfo } from 'virtual:pwa-info'
|
||||||
import type { Link } from '@unhead/schema'
|
import type { Link } from '@unhead/schema'
|
||||||
import type { Directions } from 'vue-i18n-routing'
|
import type { Directions } from 'vue-i18n-routing'
|
||||||
import { APP_NAME, STORAGE_KEY_LANG } from '~/constants'
|
import { APP_NAME, COOKIE_MAX_AGE, STORAGE_KEY_LANG } from '~/constants'
|
||||||
import type { LocaleObject } from '#i18n'
|
import type { LocaleObject } from '#i18n'
|
||||||
|
|
||||||
export function setupPageHeader() {
|
export function setupPageHeader() {
|
||||||
|
@ -49,28 +49,27 @@ export function setupPageHeader() {
|
||||||
|
|
||||||
export async function setupI18n() {
|
export async function setupI18n() {
|
||||||
const { locale, setLocale, locales } = useI18n()
|
const { locale, setLocale, locales } = useI18n()
|
||||||
const nuxtApp = useNuxtApp()
|
const cookieLocale = useCookie(STORAGE_KEY_LANG, { maxAge: COOKIE_MAX_AGE })
|
||||||
nuxtApp.hook('app:suspense:resolve', async () => {
|
const isFirstVisit = cookieLocale.value == null
|
||||||
const isFirstVisit = process.server ? false : !window.localStorage.getItem(STORAGE_KEY_LANG)
|
|
||||||
const localeStorage = process.server ? ref('en-US') : useLocalStorage(STORAGE_KEY_LANG, locale.value)
|
|
||||||
|
|
||||||
if (isFirstVisit) {
|
if (process.client && isFirstVisit) {
|
||||||
const userLang = (navigator.language || 'en-US').toLowerCase()
|
const userLang = (navigator.language || 'en-US').toLowerCase()
|
||||||
// cause vue-i18n not explicit export LocaleObject type
|
// cause vue-i18n not explicit export LocaleObject type
|
||||||
const supportLocales = unref(locales) as { code: string }[]
|
const supportLocales = unref(locales) as { code: string }[]
|
||||||
const lang = supportLocales.find(locale => userLang.startsWith(locale.code.toLowerCase()))?.code
|
const lang = supportLocales.find(locale => userLang.startsWith(locale.code.toLowerCase()))?.code
|
||||||
|| supportLocales.find(locale => userLang.startsWith(locale.code.split('-')[0]))?.code
|
|| supportLocales.find(locale => userLang.startsWith(locale.code.split('-')[0]))?.code
|
||||||
localeStorage.value = lang || 'en-US'
|
cookieLocale.value = lang || 'en-US'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (localeStorage.value !== locale.value)
|
if (cookieLocale.value && cookieLocale.value !== locale.value)
|
||||||
await setLocale(localeStorage.value)
|
await setLocale(cookieLocale.value)
|
||||||
|
|
||||||
|
if (process.client) {
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
localeStorage.value = locale.value
|
cookieLocale.value = locale.value
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function setupEmojis() {
|
export async function setupEmojis() {
|
||||||
if (process.client) {
|
if (process.client) {
|
||||||
|
|
|
@ -19,7 +19,10 @@ export const STORAGE_KEY_HIDE_EXPLORE_TAGS_TIPS = 'elk-hide-explore-tags-tips'
|
||||||
export const STORAGE_KEY_NOTIFICATION = 'elk-notification'
|
export const STORAGE_KEY_NOTIFICATION = 'elk-notification'
|
||||||
export const STORAGE_KEY_NOTIFICATION_POLICY = 'elk-notification-policy'
|
export const STORAGE_KEY_NOTIFICATION_POLICY = 'elk-notification-policy'
|
||||||
|
|
||||||
|
export const COOKIE_MAX_AGE = 10 * 365 * 24 * 60 * 60 * 1000
|
||||||
|
|
||||||
export const COOKIE_KEY_FONT_SIZE = 'elk-font-size'
|
export const COOKIE_KEY_FONT_SIZE = 'elk-font-size'
|
||||||
export const COOKIE_KEY_COLOR_MODE = 'elk-color-mode'
|
export const COOKIE_KEY_COLOR_MODE = 'elk-color-mode'
|
||||||
|
export const COOKIE_KEY_LOCALE = 'elk-locale'
|
||||||
|
|
||||||
export const HANDLED_MASTO_URLS = /^(https?:\/\/)?([\w\d-]+\.)+\w+\/(@[@\w\d-\.]+)(\/objects)?(\/\d+)?$/
|
export const HANDLED_MASTO_URLS = /^(https?:\/\/)?([\w\d-]+\.)+\w+\/(@[@\w\d-\.]+)(\/objects)?(\/\d+)?$/
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import type { ColorMode } from '~/types'
|
import type { ColorMode } from '~/types'
|
||||||
import { InjectionKeyColorMode } from '~/constants/symbols'
|
import { InjectionKeyColorMode } from '~/constants/symbols'
|
||||||
import { COOKIE_KEY_COLOR_MODE } from '~/constants'
|
import { COOKIE_KEY_COLOR_MODE, COOKIE_MAX_AGE } from '~/constants'
|
||||||
|
|
||||||
export default defineNuxtPlugin((nuxt) => {
|
export default defineNuxtPlugin((nuxt) => {
|
||||||
const cookieColorMode = useCookie<ColorMode | null>(COOKIE_KEY_COLOR_MODE, { default: () => null })
|
const cookieColorMode = useCookie<ColorMode | null>(COOKIE_KEY_COLOR_MODE, { maxAge: COOKIE_MAX_AGE })
|
||||||
|
|
||||||
const preferColorMode = process.server ? computed(() => 'light') : usePreferredColorScheme()
|
const preferColorMode = process.server ? computed(() => 'light') : usePreferredColorScheme()
|
||||||
const colorMode = computed<ColorMode>({
|
const colorMode = computed<ColorMode>({
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import type { FontSize } from '~/types'
|
import type { FontSize } from '~/types'
|
||||||
import { InjectionKeyFontSize } from '~/constants/symbols'
|
import { InjectionKeyFontSize } from '~/constants/symbols'
|
||||||
import { COOKIE_KEY_FONT_SIZE } from '~/constants'
|
import { COOKIE_KEY_FONT_SIZE, COOKIE_MAX_AGE } from '~/constants'
|
||||||
import { fontSizeMap } from '~/constants/options'
|
import { fontSizeMap } from '~/constants/options'
|
||||||
|
|
||||||
export default defineNuxtPlugin((nuxt) => {
|
export default defineNuxtPlugin((nuxt) => {
|
||||||
const DEFAULT = 'md'
|
const DEFAULT = 'md'
|
||||||
const cookieFontSize = useCookie<FontSize>(COOKIE_KEY_FONT_SIZE, { default: () => DEFAULT })
|
const cookieFontSize = useCookie<FontSize>(COOKIE_KEY_FONT_SIZE, { default: () => DEFAULT, maxAge: COOKIE_MAX_AGE })
|
||||||
nuxt.vueApp.provide(InjectionKeyFontSize, cookieFontSize)
|
nuxt.vueApp.provide(InjectionKeyFontSize, cookieFontSize)
|
||||||
|
|
||||||
if (!process.server) {
|
if (!process.server) {
|
||||||
|
|
Loading…
Reference in New Issue