Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@
"pnpm": {
"overrides": {
"vite": "^6.0.0",
"vue": "3.5.22"
"vue": "3.6.0-alpha.2"
},
"onlyBuiltDependencies": [
"@parcel/watcher",
Expand Down
13 changes: 10 additions & 3 deletions packages/vue-i18n-core/src/composer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {
isString,
warn
} from '@intlify/shared'
import { computed, getCurrentInstance, ref, shallowRef, watch } from 'vue'
import { computed, ref, shallowRef, watch } from 'vue'
import { I18nErrorCodes, createI18nError } from './errors'
import { VERSION } from './misc'
import {
Expand All @@ -49,7 +49,13 @@ import {
SetPluralRulesSymbol,
TranslateVNodeSymbol
} from './symbols'
import { createTextNode, getComponentOptions, getLocaleMessages, handleFlatJson } from './utils'
import {
createTextNode,
getComponentOptions,
getCurrentInstance,
getLocaleMessages,
handleFlatJson
} from './utils'
import { I18nWarnCodes, getWarnMessage } from './warnings'

import type {
Expand Down Expand Up @@ -104,6 +110,7 @@ import type { VueDevToolsEmitter } from '@intlify/devtools-types'
import type {
ComponentInternalInstance,
ComputedRef,
GenericComponentInstance,
VNode,
VNodeArrayChildren,
WritableComputedRef
Expand Down Expand Up @@ -221,7 +228,7 @@ export type DefaultNumberFormatSchema<
export type MissingHandler = (
locale: Locale,
key: Path,
instance?: ComponentInternalInstance,
instance?: ComponentInternalInstance | GenericComponentInstance,
type?: string
) => string | void

Expand Down
23 changes: 11 additions & 12 deletions packages/vue-i18n-core/src/devtools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type {
Hooks,
InspectedComponentData
} from '@vue/devtools-api'
import type { App, ComponentInternalInstance } from 'vue'
import type { App, ComponentInternalInstance, GenericComponentInstance } from 'vue'
import type { Composer } from './composer'
import type { I18n, I18nInternal } from './i18n'

Expand Down Expand Up @@ -61,12 +61,8 @@ export async function enableDevTools(app: App, i18n: _I18n): Promise<boolean> {
})

api.on.inspectComponent(({ componentInstance, instanceData }) => {
if (
componentInstance.vnode.el &&
componentInstance.vnode.el.__VUE_I18N__ &&
instanceData
) {
inspectComposer(instanceData, componentInstance.vnode.el.__VUE_I18N__ as Composer)
if (componentInstance.__VUE_I18N__ && instanceData) {
inspectComposer(instanceData, componentInstance.__VUE_I18N__ as Composer)
}
})

Expand All @@ -83,7 +79,7 @@ export async function enableDevTools(app: App, i18n: _I18n): Promise<boolean> {
}
})

const roots = new Map<App, ComponentInternalInstance>()
const roots = new Map<App, ComponentInternalInstance | GenericComponentInstance>()
api.on.getInspectorState(async payload => {
if (payload.app === app && payload.inspectorId === 'vue-i18n-resource-inspector') {
api.unhighlightElement()
Expand Down Expand Up @@ -138,9 +134,9 @@ function updateComponentTreeTags(
): void {
// prettier-ignore
const global = i18n.global
if (instance && instance.vnode.el && instance.vnode.el.__VUE_I18N__) {
if (instance && instance.__VUE_I18N__) {
// add custom tags local scope only
if (instance.vnode.el.__VUE_I18N__ !== global) {
if (instance.__VUE_I18N__ !== global) {
const tag = {
label: `i18n (${getI18nScopeLable(instance)} Scope)`,
textColor: 0x000000,
Expand Down Expand Up @@ -263,8 +259,11 @@ function registerScope(payload: HookPayloads[Hooks.GET_INSPECTOR_TREE], i18n: _I
}
}

function getComponentInstance(nodeId: string, i18n: _I18n): ComponentInternalInstance | null {
let instance: ComponentInternalInstance | null = null
function getComponentInstance(
nodeId: string,
i18n: _I18n
): ComponentInternalInstance | GenericComponentInstance | null {
let instance: ComponentInternalInstance | GenericComponentInstance | null = null

if (nodeId !== 'global') {
for (const [component, composer] of i18n.__instances.entries()) {
Expand Down
44 changes: 23 additions & 21 deletions packages/vue-i18n-core/src/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,24 @@ import {
makeSymbol,
warn
} from '@intlify/shared'
import { effectScope, getCurrentInstance, inject, isRef, onMounted, onUnmounted } from 'vue'
import { effectScope, inject, isRef, onMounted, onUnmounted } from 'vue'
import { createComposer } from './composer'
import { addTimelineEvent, enableDevTools } from './devtools'
import { I18nErrorCodes, createI18nError } from './errors'
import { apply as applyPlugin } from './plugin/next'
import { DisableEmitter, DisposeSymbol, EnableEmitter } from './symbols'
import { adjustI18nResources, getComponentOptions } from './utils'
import { adjustI18nResources, getComponentOptions, getCurrentInstance } from './utils'
import { I18nWarnCodes, getWarnMessage } from './warnings'

import type { FallbackLocale, Locale, LocaleParams, SchemaParams } from '@intlify/core-base'
import type { VueDevToolsEmitter, VueDevToolsEmitterEvents } from '@intlify/devtools-types'
import type { App, ComponentInternalInstance, EffectScope, InjectionKey } from 'vue'
import type {
App,
ComponentInternalInstance,
EffectScope,
GenericComponentInstance,
InjectionKey
} from 'vue'
import type {
Composer,
ComposerInternalOptions,
Expand Down Expand Up @@ -136,17 +142,17 @@ export interface I18nInternal<
OptionLocale = Locale
> {
__instances: Map<
ComponentInternalInstance,
ComponentInternalInstance | GenericComponentInstance,
Composer<Messages, DateTimeFormats, NumberFormats, OptionLocale>
>
__getInstance<Instance extends Composer<Messages, DateTimeFormats, NumberFormats, OptionLocale>>(
component: ComponentInternalInstance
component: ComponentInternalInstance | GenericComponentInstance
): Instance | null
__setInstance<Instance extends Composer<Messages, DateTimeFormats, NumberFormats, OptionLocale>>(
component: ComponentInternalInstance,
component: ComponentInternalInstance | GenericComponentInstance,
instance: Instance
): void
__deleteInstance(component: ComponentInternalInstance): void
__deleteInstance(component: ComponentInternalInstance | GenericComponentInstance): void
__composerExtend?: ComposerExtender
}

Expand Down Expand Up @@ -556,7 +562,7 @@ function createGlobal(options: I18nOptions): [EffectScope, Composer] {
return [scope, obj]
}

function getI18nInstance(instance: ComponentInternalInstance): I18n {
function getI18nInstance(instance: ComponentInternalInstance | GenericComponentInstance): I18n {
const i18n = inject(
!instance.isCE ? instance.appContext.app.__VUE_I18N_SYMBOL__! : I18nInjectionKey
)
Expand Down Expand Up @@ -588,12 +594,13 @@ function getGlobalComposer(i18n: I18n): Composer {

function getComposer(
i18n: I18n,
target: ComponentInternalInstance,
target: ComponentInternalInstance | GenericComponentInstance,
useComponent = false
): Composer | null {
let composer: Composer | null = null
const root = target.root
let current: ComponentInternalInstance | null = getParentComponentInstance(target, useComponent)
let current: ComponentInternalInstance | GenericComponentInstance | null =
getParentComponentInstance(target, useComponent)
while (current != null) {
const i18nInternal = i18n as unknown as I18nInternal
composer = i18nInternal.__getInstance(current)
Expand All @@ -610,7 +617,7 @@ function getComposer(
}

function getParentComponentInstance(
target: ComponentInternalInstance | null,
target: ComponentInternalInstance | GenericComponentInstance | null,
useComponent = false
) {
if (target == null) {
Expand All @@ -622,16 +629,16 @@ function getParentComponentInstance(

function setupLifeCycle(
i18n: I18nInternal,
target: ComponentInternalInstance,
target: ComponentInternalInstance | GenericComponentInstance,
composer: Composer
): void {
let emitter: VueDevToolsEmitter | null = null

// eslint-disable-next-line vue-composable/lifecycle-placement -- NOTE(kazupon): not Vue component
onMounted(() => {
// inject composer instance to DOM for intlify-devtools
if ((__DEV__ || __FEATURE_PROD_VUE_DEVTOOLS__) && !__NODE_JS__ && target.vnode.el) {
target.vnode.el.__VUE_I18N__ = composer
if ((__DEV__ || __FEATURE_PROD_VUE_DEVTOOLS__) && !__NODE_JS__) {
target.__VUE_I18N__ = composer
emitter = createEmitter<VueDevToolsEmitterEvents>()
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const _composer = composer as any
Expand All @@ -646,15 +653,10 @@ function setupLifeCycle(
const _composer = composer as any

// remove composer instance from DOM for intlify-devtools
if (
(__DEV__ || __FEATURE_PROD_VUE_DEVTOOLS__) &&
!__NODE_JS__ &&
target.vnode.el &&
target.vnode.el.__VUE_I18N__
) {
if ((__DEV__ || __FEATURE_PROD_VUE_DEVTOOLS__) && !__NODE_JS__ && target.__VUE_I18N__) {
emitter && emitter.off('*', addTimelineEvent)
_composer[DisableEmitter] && _composer[DisableEmitter]()
delete target.vnode.el.__VUE_I18N__
delete target.__VUE_I18N__
}
i18n.__deleteInstance(target)

Expand Down
17 changes: 15 additions & 2 deletions packages/vue-i18n-core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@ import {
isString,
warn
} from '@intlify/shared'
import * as Vue from 'vue'
import { Text, createVNode } from 'vue'
import { I18nWarnCodes, getWarnMessage } from './warnings'

import type { Locale, MessageResolver } from '@intlify/core-base'
import type { ComponentInternalInstance, RendererElement, RendererNode } from 'vue'
import type {
ComponentInternalInstance,
GenericComponentInstance,
RendererElement,
RendererNode
} from 'vue'
import type { Composer, ComposerOptions, CustomBlocks, VueMessageType } from './composer'

type GetLocaleMessagesOptions<Messages = {}> = {
Expand Down Expand Up @@ -154,7 +160,9 @@ export function getLocaleMessages<Messages = {}>(
return ret as { [K in keyof Messages]: Messages[K] }
}

export function getComponentOptions(instance: ComponentInternalInstance): any {
export function getComponentOptions(
instance: ComponentInternalInstance | GenericComponentInstance
): any {
return instance.type
}

Expand Down Expand Up @@ -205,3 +213,8 @@ export function adjustI18nResources(
export function createTextNode(key: string): any {
return createVNode(Text, null, key, 0)
}

export function getCurrentInstance(): GenericComponentInstance | ComponentInternalInstance | null {
// @ts-ignore -- NOTE(kazupon): for Vue 3.6
return Vue.currentInstance || Vue.getCurrentInstance()
}
21 changes: 20 additions & 1 deletion packages/vue-i18n-core/src/vue.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { InjectionKey } from 'vue'
import type { Composer } from './composer'
import type { I18n, I18nInternal } from './i18n'

declare module 'vue' {
Expand All @@ -14,8 +15,26 @@ declare module 'vue' {
export interface ComponentInternalInstance {
/**
* @internal
* iskk custom element?
* whether target component is custom element
*/
isCE?: boolean
/**
* @internal
* for vue/devtools i18n composer hook
*/
__VUE_I18N__?: Composer
}

export interface GenericComponentInstance {
/**
* @internal
* whether target component is custom element
*/
isCE?: boolean
/**
* @internal
* for vue/devtools i18n composer hook
*/
__VUE_I18N__?: Composer
}
}
3 changes: 2 additions & 1 deletion packages/vue-i18n-core/test/i18n.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ import {
setDevToolsHook
} from '@intlify/core-base'
import { createEmitter } from '@intlify/shared'
import { defineComponent, defineCustomElement, getCurrentInstance, h, nextTick, ref } from 'vue'
import { defineComponent, defineCustomElement, h, nextTick, ref } from 'vue'
import { errorMessages, I18nErrorCodes } from '../src/errors'
import { createI18n, useI18n } from '../src/i18n'
import { getCurrentInstance } from '../src/utils'
import { pluralRules as _pluralRules, mount, randStr } from './helper'

import type { IntlifyDevToolsEmitterHooks } from '@intlify/devtools-types'
Expand Down
3 changes: 2 additions & 1 deletion packages/vue-i18n-core/test/issues.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ import {
resolveValue,
setDevToolsHook
} from '@intlify/core-base'
import { defineComponent, getCurrentInstance, nextTick, ref } from 'vue'
import { defineComponent, nextTick, ref } from 'vue'
import { createI18n, useI18n } from '../src/i18n'
import { getCurrentInstance } from '../src/utils'
import { ast } from './fixtures/ast'
import { mount } from './helper'

Expand Down
13 changes: 7 additions & 6 deletions packages/vue-i18n-core/test/wc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@
* @vitest-environment jsdom
*/

import { h, provide, nextTick, defineCustomElement, getCurrentInstance } from 'vue'
import {
compile,
fallbackWithLocaleChain,
registerLocaleFallbacker,
registerMessageCompiler,
resolveValue,
registerMessageResolver,
fallbackWithLocaleChain,
registerLocaleFallbacker
resolveValue
} from '@intlify/core-base'
import { createI18n, useI18n, I18nInjectionKey } from '../src/index'
import { defineCustomElement, h, nextTick, provide } from 'vue'
import { createI18n, I18nInjectionKey, useI18n } from '../src/index'
import { getCurrentInstance } from '../src/utils'
import { randStr } from './helper'

import type { VueElement, ComponentOptions } from 'vue'
import type { ComponentOptions, VueElement } from 'vue'

const container = document.createElement('div')
document.body.appendChild(container)
Expand Down
Loading
Loading