Skip to content

Conversation

@kazupon
Copy link
Member

@kazupon kazupon commented Nov 22, 2025

back-ported from master branch (v12)
related #2299

Summary by CodeRabbit

  • Chores
    • Updated Vue runtime dependency to version 3.6.0-alpha.4 for improved compatibility.
    • Enhanced component instance handling across the library to support broader component types, including custom element support.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 22, 2025

Walkthrough

This PR adds support for Vue 3.6's GenericComponentInstance type across the vue-i18n core library. Changes include broadening component instance type unions in internal maps and function signatures, shifting devtools linkage from DOM-based to instance-based attachment, extracting getCurrentInstance into a local utils module, and updating the Vue version override from 3.5.13 to 3.6.0-alpha.4.

Changes

Cohort / File(s) Summary
Vue Version Dependency
package.json
Updated pnpm.overrides.vue from 3.5.13 to 3.6.0-alpha.4 for Vue 3.6 alpha support
Core Type Broadening & GenericComponentInstance Support
packages/vue-i18n-core/src/i18n.ts, packages/vue-i18n-core/src/composer.ts, packages/vue-i18n-core/src/devtools.ts
Added GenericComponentInstance to Vue type imports; broadened all component instance type unions from ComponentInternalInstance to ComponentInternalInstance | GenericComponentInstance across instance maps and function parameters (getI18nInstance, getComposer, setupLifeCycle, etc.); updated MissingHandler signature to accept both instance types
Devtools Linkage Refactor
packages/vue-i18n-core/src/i18n.ts, packages/vue-i18n-core/src/devtools.ts
Changed devtools integration from DOM-based (vnode.el.__VUE_I18N__) to instance-based (instance.__VUE_I18N__) attachment; updated root instance map type and getComponentInstance return type to include GenericComponentInstance
Utilities & Import Restructuring
packages/vue-i18n-core/src/utils.ts
Expanded getComponentOptions parameter type to accept ComponentInternalInstance | GenericComponentInstance; introduced new exported getCurrentInstance function for Vue 3.6 compatibility
Test Import Updates
packages/vue-i18n-core/test/i18n.test.ts, packages/vue-i18n-core/test/issues.test.ts, packages/vue-i18n-core/test/wc.test.ts
Moved getCurrentInstance import source from 'vue' to '../src/utils'; consolidated and reorganized import statements in web components test file

Sequence Diagram(s)

sequenceDiagram
    participant Component as Vue Component<br/>(ComponentInternalInstance or<br/>GenericComponentInstance)
    participant I18n as I18n Core
    participant Devtools as Devtools Integration
    participant Utils as Utils

    Note over Component,Utils: Old Flow (Vue 3.5)
    Component->>I18n: Mount with ComponentInternalInstance
    I18n->>I18n: Store in __instances map<br/>(keyed by ComponentInternalInstance)
    I18n->>Devtools: Link via vnode.el.__VUE_I18N__
    Devtools->>Devtools: Check componentInstance.vnode.el.__VUE_I18N__

    Note over Component,Utils: New Flow (Vue 3.6+)
    Component->>I18n: Mount with ComponentInternalInstance<br/>or GenericComponentInstance
    I18n->>I18n: Store in __instances map<br/>(keyed by ComponentInternalInstance |<br/>GenericComponentInstance)
    I18n->>Component: Assign instance.__VUE_I18N__<br/>(direct instance attachment)
    Devtools->>Component: Check componentInstance.__VUE_I18N__<br/>(direct instance lookup)
    Devtools-->>Devtools: Simplified resolution logic
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Files requiring extra attention during review:
    • packages/vue-i18n-core/src/i18n.ts — Critical changes to devtools linkage logic (vnode.el-based → instance-based) and GenericComponentInstance interface definition; verify all instance map operations and lifecycle wiring
    • packages/vue-i18n-core/src/devtools.ts — Verify the transition from componentInstance.vnode.el.__VUE_I18N__ checks to direct componentInstance.__VUE_I18N__ lookups across all inspection and tag-update branches
    • packages/vue-i18n-core/src/utils.ts — Ensure the new getCurrentInstance implementation correctly handles both GenericComponentInstance and ComponentInternalInstance for Vue 3.6 compatibility

Possibly related PRs

  • feat: compatible Vue3 vapor mode #2299 — Duplicates the same core changes: adds GenericComponentInstance support, widens component instance types, moves getCurrentInstance to utils, and updates the Vue version override; appears to be the same feature implemented in parallel
  • fix: error on duplicate useI18n calling on local scope #2203 — Modifies packages/vue-i18n-core/src/i18n.ts to guard useI18n against duplicate local calls; overlaps in the same i18n implementation file with instance wiring logic

Poem

🐰 A rabbit hops through Vue 3.6's door,
GenericInstance types we now explore,
No more vnode.el, direct linkage instead,
Devtools dance on instance threads,
Web Components and Custom Elements fed! 🌿

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: compatible Vue3 vapor mode for v11' accurately describes the main objective of the PR—adding Vue 3 Vapor mode compatibility to v11 by expanding component instance type handling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/vue3-vapor-for-v11

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@kazupon kazupon added the Type: Feature Includes new features label Nov 22, 2025
@kazupon
Copy link
Member Author

kazupon commented Nov 22, 2025

@coderabbitai
please review this PR!

@coderabbitai
Copy link

coderabbitai bot commented Nov 22, 2025

@kazupon I'll review this PR for you right away! Let me analyze the changes for Vue 3 Vapor mode compatibility.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 22, 2025

Open in StackBlitz

@intlify/core

npm i https://pkg.pr.new/@intlify/core@2320

@intlify/core-base

npm i https://pkg.pr.new/@intlify/core-base@2320

@intlify/devtools-types

npm i https://pkg.pr.new/@intlify/devtools-types@2320

@intlify/message-compiler

npm i https://pkg.pr.new/@intlify/message-compiler@2320

petite-vue-i18n

npm i https://pkg.pr.new/petite-vue-i18n@2320

@intlify/shared

npm i https://pkg.pr.new/@intlify/shared@2320

vue-i18n

npm i https://pkg.pr.new/vue-i18n@2320

@intlify/vue-i18n-core

npm i https://pkg.pr.new/@intlify/vue-i18n-core@2320

commit: 9131fd9

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
package.json (1)

158-160: Consider aligning vue devDependency with the pnpm override

devDependencies.vue is still 3.5.13 while pnpm.overrides.vue forces 3.6.0-alpha.4. That works, but it’s easy to misread the effective Vue version from the manifest. Consider bumping the devDependency to the same version or adding a short comment in release notes/PR description so future readers understand why an alpha override is in place.

Also applies to: 187-189

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4786d3d and 9131fd9.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • package.json (1 hunks)
  • packages/vue-i18n-core/src/composer.ts (4 hunks)
  • packages/vue-i18n-core/src/devtools.ts (5 hunks)
  • packages/vue-i18n-core/src/i18n.ts (11 hunks)
  • packages/vue-i18n-core/src/utils.ts (3 hunks)
  • packages/vue-i18n-core/test/i18n.test.ts (1 hunks)
  • packages/vue-i18n-core/test/issues.test.ts (1 hunks)
  • packages/vue-i18n-core/test/wc.test.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: release
  • GitHub Check: Build (macos-latest, 20)
  • GitHub Check: Build (ubuntu-latest, 20)
  • GitHub Check: Build (windows-latest, 20)
🔇 Additional comments (5)
packages/vue-i18n-core/test/i18n.test.ts (1)

37-37: Tests now use the shared getCurrentInstance helper

Switching the test import to ../src/utils keeps tests aligned with the runtime abstraction and avoids depending directly on Vue’s getCurrentInstance API.

packages/vue-i18n-core/test/issues.test.ts (1)

33-33: Issue tests updated to use utils getCurrentInstance

Pointing these tests at ../src/utils is consistent with the new runtime abstraction and avoids hard-coding Vue internals in the test suite.

packages/vue-i18n-core/test/wc.test.ts (1)

5-19: WC tests aligned with runtime helpers and fallback registration

Registering the compiler, resolver, and locale fallbacker and switching to createI18n/I18nInjectionKey/getCurrentInstance mirrors the production setup for web components and custom blocks. This keeps the WC coverage representative of actual usage.

Also applies to: 23-27

packages/vue-i18n-core/src/i18n.ts (1)

31-35: Instance tracking and lifecycle now handle both ComponentInternalInstance and GenericComponentInstance coherently

Using ComponentInternalInstance | GenericComponentInstance as the key type for __instances, widening the internal APIs (__getInstance/__setInstance/__deleteInstance, getI18nInstance, getComposer, getParentComponentInstance, setupLifeCycle), and attaching the composer to target.__VUE_I18N__ on mount (and deleting it on unmount) all align with the new utils/devtools contracts and Vue 3.6’s generic instances. The isCE gate in getI18nInstance is a nice touch to route web components through I18nInjectionKey while regular components still use the app’s plugin symbol.

Please run the updated WC tests and a parent-scope useI18n({ useScope: 'parent' }) scenario under your targeted Vue 3.6/Vapor build to confirm that:

  • custom elements correctly resolve the injected i18n via I18nInjectionKey, and
  • parent-scope resolution via getParentComponentInstance behaves as expected with GenericComponentInstance.

Also applies to: 49-53, 79-106, 262-296, 523-548, 837-854, 875-913, 915-926, 928-966

packages/vue-i18n-core/src/composer.ts (1)

41-42: Clarify the TypeScript breaking change for release notes

The web search confirms the assignability issue is more definitive than stated: functions explicitly typed with instance: ComponentInternalInstance are not assignable to the widened callback under strictFunctionTypes: true (not just "may see stricter assignability"). This is a breaking change that should be clearly documented in release notes with explicit mention of the strictFunctionTypes requirement and recommended migration path (e.g., switching to callback-inferred typing or expanding handler types to ComponentInternalInstance | GenericComponentInstance).

Comment on lines +27 to +31
import type {
App,
ComponentInternalInstance,
GenericComponentInstance
} from 'vue'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Devtools now bind to instance.__VUE_I18N__, consistent with new lifecycle wiring

Reading the composer from componentInstance.__VUE_I18N__ (and tagging tree nodes only when it differs from the global composer) matches how setupLifeCycle in i18n.ts now attaches/removes the composer on component instances, including generic ones. The widened roots and getComponentInstance typings to ComponentInternalInstance | GenericComponentInstance are in line with that model.

Also applies to: 72-97, 115-118, 168-189, 321-327


🏁 Script executed:

#!/bin/bash
# Inspect all uses of `__VUE_I18N__` to ensure devtools and lifecycle wiring are consistent.
rg -n "__VUE_I18N__" packages/vue-i18n-core -C3

Length of output: 7001


Critical inconsistency: devtools reads from component instance, but mixin still attaches to DOM element

The verification reveals a mismatch between binding locations:

  • i18n.ts (setupLifeCycle, composition API): attaches __VUE_I18N__ to the component instance (target.__VUE_I18N__)
  • devtools.ts: reads from the component instance (componentInstance.__VUE_I18N__)
  • mixins.ts (options API): attaches __VUE_I18N__ to the DOM element (this.$el.__VUE_I18N__)

The devtools code will not discover composers attached via the mixin path, breaking devtools inspection for legacy/options-API components. Either mixins.ts needs to attach to the component instance instead of the DOM element, or devtools needs to fall back to checking the DOM element for legacy compatibility.

🤖 Prompt for AI Agents
In packages/vue-i18n-core/src/devtools.ts around lines 27 to 31, devtools
currently only reads __VUE_I18N__ from the component instance but mixins attach
it to the DOM element; update devtools to fallback to checking the component's
root DOM element if componentInstance.__VUE_I18N__ is undefined (i.e., check
componentInstance.vnode?.el or componentInstance?.proxy?.$el for __VUE_I18N__),
so it discovers composers attached via the options/mixin path; implement the
fallback lookup and use whichever composer object is found.

Comment on lines +13 to 15
import * as Vue from 'vue'
import { Text, createVNode } from 'vue'
import { I18nWarnCodes, getWarnMessage } from './warnings'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Centralized getCurrentInstance/GenericComponentInstance support looks consistent

Importing * as Vue and introducing getCurrentInstance() plus a ComponentInternalInstance | GenericComponentInstance-aware getComponentOptions() lines up with the wider instance usage in composer, i18n, and devtools. The Vue.currentInstance || Vue.getCurrentInstance() fallback is a reasonable way to bridge Vue 3.6 behavior with earlier runtimes in one place.

Also applies to: 19-23, 168-172, 222-228


🏁 Script executed:

#!/bin/bash
# Check for any remaining direct `getCurrentInstance` imports/usages now that utils exposes a wrapper.
rg -n "getCurrentInstance" packages/vue-i18n-core -C3

Length of output: 9739


Update mixins.ts to use the getCurrentInstance wrapper from utils

The centralization goal is undermined: packages/vue-i18n-core/src/mixins.ts imports getCurrentInstance directly from 'vue' (line 2) instead of from './utils'. This bypasses the Vue 3.6 compatibility wrapper entirely. Lines 44 and 134 in mixins.ts should use the wrapper to ensure consistent handling.

Change line 2 in mixins.ts:

- import { getCurrentInstance } from 'vue'
+ import { getCurrentInstance } from './utils'
🤖 Prompt for AI Agents
In packages/vue-i18n-core/src/mixins.ts around lines 44 and 134, the file
imports getCurrentInstance directly from 'vue' instead of using the
compatibility wrapper in ./utils; update the import statement to import
getCurrentInstance from './utils' (remove it from the named imports from 'vue'
and add it to the local utils import) so both usages at the specified lines call
the wrapper, preserving Vue 3.6 compatibility and centralized behavior.

@kazupon kazupon merged commit 100c669 into v11 Nov 22, 2025
27 checks passed
@kazupon kazupon deleted the feat/vue3-vapor-for-v11 branch November 22, 2025 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: Feature Includes new features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants