You've already forked AstralRinth
forked from didirus/AstralRinth
feat: remove nuxt i18n for in house i18n for web (#5131)
* feat: remove nuxt i18n for in house * cleanup: remove old nuxt/i18n patch * prepr --------- Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
import IntlMessageFormat, { type FormatXMLElementFn, type PrimitiveType } from 'intl-messageformat'
|
||||
import { computed, useSlots, type VNode } from 'vue'
|
||||
|
||||
import { getSafeI18n, type MessageDescriptor } from '../../composables/i18n'
|
||||
import type { MessageDescriptor } from '../../composables/i18n'
|
||||
import { injectI18n } from '../../providers/i18n'
|
||||
|
||||
const props = defineProps<{
|
||||
messageId: MessageDescriptor
|
||||
@@ -10,7 +11,7 @@ const props = defineProps<{
|
||||
}>()
|
||||
|
||||
const slots = useSlots()
|
||||
const { t, locale } = getSafeI18n()
|
||||
const { t, locale } = injectI18n()
|
||||
|
||||
const formattedParts = computed(() => {
|
||||
const key = props.messageId.id
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { computed, type ComputedRef } from 'vue'
|
||||
|
||||
import { getSafeI18n } from './i18n'
|
||||
import { injectI18n } from '../providers/i18n'
|
||||
|
||||
export type Formatter = (value: Date | number, options?: FormatOptions) => string
|
||||
|
||||
@@ -11,7 +11,7 @@ export interface FormatOptions {
|
||||
const formatters = new Map<string, ComputedRef<Intl.RelativeTimeFormat>>()
|
||||
|
||||
export function useRelativeTime(): Formatter {
|
||||
const { locale } = getSafeI18n()
|
||||
const { locale } = injectI18n()
|
||||
|
||||
const formatterRef = computed(
|
||||
() =>
|
||||
|
||||
@@ -1,35 +1,8 @@
|
||||
import IntlMessageFormat from 'intl-messageformat'
|
||||
import type { Ref } from 'vue'
|
||||
import type { CompileError, Composer, MessageCompiler, MessageContext } from 'vue-i18n'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type { CompileError, MessageCompiler, MessageContext } from 'vue-i18n'
|
||||
|
||||
declare const useNuxtApp: (() => { $i18n?: Pick<Composer, 't' | 'locale'> }) | undefined
|
||||
|
||||
/**
|
||||
* Get i18n instance, preferring Nuxt's $i18n to avoid vue-i18n's
|
||||
* getCurrentInstance() issues on edge runtimes with concurrent SSR requests.
|
||||
*/
|
||||
export function getSafeI18n(): Pick<Composer, 't' | 'locale'> {
|
||||
// Try Nuxt's $i18n first (avoids Error 27 on Cloudflare Workers)
|
||||
if (typeof useNuxtApp === 'function') {
|
||||
try {
|
||||
const nuxtApp = useNuxtApp()
|
||||
const $i18n = nuxtApp.$i18n
|
||||
if ($i18n) {
|
||||
return { t: $i18n.t, locale: $i18n.locale }
|
||||
}
|
||||
console.warn('[getSafeI18n] useNuxtApp() succeeded but $i18n is falsy:', $i18n)
|
||||
} catch (e) {
|
||||
console.warn('[getSafeI18n] useNuxtApp() threw:', e)
|
||||
}
|
||||
} else {
|
||||
console.debug('[getSafeI18n] useNuxtApp not available, using vue-i18n fallback')
|
||||
}
|
||||
|
||||
console.log('FALLBACK TO useI18n!!!')
|
||||
// Fallback to vue-i18n's useI18n (used in Tauri app or if Nuxt context unavailable)
|
||||
return useI18n()
|
||||
}
|
||||
import { injectI18n } from '../providers/i18n'
|
||||
|
||||
export interface MessageDescriptor {
|
||||
id: string
|
||||
@@ -55,7 +28,6 @@ export interface LocaleDefinition {
|
||||
code: string
|
||||
name: string
|
||||
dir?: 'ltr' | 'rtl'
|
||||
// For @nuxtjs/i18n v9 compatibility
|
||||
iso?: string
|
||||
file?: string
|
||||
}
|
||||
@@ -199,10 +171,10 @@ export interface VIntlFormatters {
|
||||
|
||||
/**
|
||||
* Composable that provides formatMessage() with the same API as @vintl/vintl.
|
||||
* Uses vue-i18n's useI18n() under the hood.
|
||||
* Uses the injected I18nContext from the provider.
|
||||
*/
|
||||
export function useVIntl(): VIntlFormatters & { locale: Ref<string> } {
|
||||
const { t, locale } = getSafeI18n()
|
||||
const { t, locale } = injectI18n()
|
||||
|
||||
function formatMessage(descriptor: MessageDescriptor, values?: Record<string, unknown>): string {
|
||||
const key = descriptor.id
|
||||
|
||||
24
packages/ui/src/providers/i18n.ts
Normal file
24
packages/ui/src/providers/i18n.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import type { InjectionKey, Ref } from 'vue'
|
||||
import { inject, provide } from 'vue'
|
||||
|
||||
// This doesn't use the architecture outlined in index.ts as it needs some custom checks + use the symbol
|
||||
export interface I18nContext {
|
||||
locale: Ref<string>
|
||||
t: (key: string, values?: Record<string, unknown>) => string
|
||||
setLocale: (locale: string) => Promise<void> | void
|
||||
}
|
||||
|
||||
export const I18N_INJECTION_KEY: InjectionKey<I18nContext> = Symbol('i18n')
|
||||
|
||||
export function injectI18n(): I18nContext {
|
||||
const context = inject(I18N_INJECTION_KEY)
|
||||
if (!context) {
|
||||
throw new Error('Injection `Symbol(i18n)` not found. Ensure the i18n plugin is installed.')
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
export function provideI18n(context: I18nContext): I18nContext {
|
||||
provide(I18N_INJECTION_KEY, context)
|
||||
return context
|
||||
}
|
||||
@@ -79,6 +79,7 @@ export function createContext<ContextValue>(
|
||||
}
|
||||
|
||||
export * from './api-client'
|
||||
export * from './i18n'
|
||||
export * from './page-context'
|
||||
export * from './project-page'
|
||||
export * from './server-context'
|
||||
|
||||
Reference in New Issue
Block a user