Skip to content

Conversation

@kazupon
Copy link
Member

@kazupon kazupon commented Oct 23, 2025

related #2234

Summary by CodeRabbit

  • New Features

    • Broadened support for generic Vue component instances for improved compatibility.
    • Exposed a utility to obtain the current component instance for runtime use.
  • Chores

    • Updated Vue override to 3.6.0-alpha.2.
    • Refactored internal instance handling and reorganized utility imports for maintainability.
  • Tests

    • Updated tests to align with the new instance handling and utility imports.

@kazupon kazupon added the Type: Feature Includes new features label Oct 23, 2025
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Oct 23, 2025

Deploying vue-i18n-next with  Cloudflare Pages  Cloudflare Pages

Latest commit: 2e2f7b2
Status: ✅  Deploy successful!
Preview URL: https://a9c0d00a.vue-i18n-next.pages.dev
Branch Preview URL: https://feat-vue-vapor3.vue-i18n-next.pages.dev

View logs

@github-actions
Copy link

Size Report

Bundles

File Size Gzip Brotli
core.esm-browser.prod.js 36.59 kB 11.46 kB 10.22 kB
core.global.prod.js 29.42 kB 10.34 kB 9.33 kB
core.runtime.esm-browser.prod.js 23.70 kB 7.67 kB 6.87 kB
core.runtime.global.prod.js 17.65 kB 6.92 kB 6.21 kB
message-compiler.esm-browser.prod.js 17.91 kB 5.66 kB 5.04 kB
message-compiler.global.prod.js 16.50 kB 5.45 kB 4.88 kB
petite-vue-i18n-core.esm-browser.prod.js 20.47 kB (+0.09 kB) 6.88 kB (+0.02 kB) 6.19 kB (+0.03 kB)
petite-vue-i18n-core.global.prod.js 15.07 kB (+0.15 kB) 5.81 kB (+0.05 kB) 5.31 kB (+0.05 kB)
petite-vue-i18n.esm-browser.prod.js 35.39 kB (+0.09 kB) 11.13 kB (+0.03 kB) 9.98 kB (+0.02 kB)
petite-vue-i18n.global.prod.js 28.04 kB (+0.16 kB) 9.60 kB (+0.05 kB) 8.71 kB (+0.03 kB)
petite-vue-i18n.runtime.esm-browser.prod.js 22.35 kB (+0.09 kB) 7.25 kB (+0.02 kB) 6.56 kB (+0.02 kB)
petite-vue-i18n.runtime.global.prod.js 16.28 kB (+0.15 kB) 6.15 kB (+0.05 kB) 5.62 kB (+0.05 kB)
vue-i18n.esm-browser.prod.js 49.05 kB (+0.09 kB) 14.91 kB (+0.01 kB) 13.36 kB (+0.03 kB)
vue-i18n.global.prod.js 38.53 kB (+0.16 kB) 13.02 kB (+0.09 kB) 11.77 kB (+0.03 kB)
vue-i18n.runtime.esm-browser.prod.js 36.00 kB (+0.09 kB) 11.07 kB (+0.02 kB) 9.96 kB (+0.03 kB)
vue-i18n.runtime.global.prod.js 26.76 kB (+0.15 kB) 9.60 kB (+0.07 kB) 8.71 kB (+0.06 kB)

Usages

Name Size Gzip Brotli
packages/size-check-core (@intlify/core) 9.22 kB 3.83 kB 3.46 kB
packages/size-check-petite-vue-i18n (petite-vue-i18n) 80.01 kB (+1.80 kB) 30.88 kB (+0.40 kB) 27.79 kB (+0.33 kB)
packages/size-check-vue-i18n (vue-i18n) 85.23 kB (+1.81 kB) 32.37 kB (+0.40 kB) 29.05 kB (+0.26 kB)

@pkg-pr-new
Copy link

pkg-pr-new bot commented Oct 23, 2025

Open in StackBlitz

@intlify/core

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

@intlify/core-base

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

@intlify/devtools-types

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

@intlify/message-compiler

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

petite-vue-i18n

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

@intlify/shared

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

vue-i18n

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

@intlify/vue-i18n-core

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

commit: 2e2f7b2

@coderabbitai
Copy link

coderabbitai bot commented Oct 26, 2025

Walkthrough

Updates pnpm Vue override to 3.6.0-alpha.2 and adapts code for Vue 3.6 compatibility by introducing GenericComponentInstance, widening component-instance types across core modules, moving getCurrentInstance into internal utils, and switching VUE_I18N tracking from vnode.el to instance properties.

Changes

Cohort / File(s) Change Summary
Dependency Management
package.json
Updated pnpm.override for Vue from 3.5.22 to 3.6.0-alpha.2
Type Augmentation
packages/vue-i18n-core/src/vue.d.ts
Added GenericComponentInstance and __VUE_I18N__?: Composer augmentation; imported Composer
Core API & Signatures
packages/vue-i18n-core/src/composer.ts, packages/vue-i18n-core/src/i18n.ts, packages/vue-i18n-core/src/devtools.ts
Widened component instance parameter types to `ComponentInternalInstance
Utilities
packages/vue-i18n-core/src/utils.ts
Added/exported `getCurrentInstance(): GenericComponentInstance
Tests / Imports
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 from vue to ../src/utils; adjusted test import ordering and added imports for fallbackWithLocaleChain / registerLocaleFallbacker where applicable

Sequence Diagram(s)

sequenceDiagram
    participant Comp as Component
    participant Setup as setupLifeCycle
    participant I18n as I18nInternal
    participant Dev as DevTools

    Note over Comp,Dev: Mount (new flow)
    Comp->>Setup: mount target (ComponentInternalInstance | GenericComponentInstance)
    Setup->>I18n: __setInstance(target, composer)
    I18n->>I18n: store in __instances (key = target)
    Setup->>Comp: set target.__VUE_I18N__ = composer
    Setup->>Dev: notify using instance.__VUE_I18N__

    Note over Comp,Dev: Unmount (new flow)
    Comp->>Setup: unmount target
    Setup->>I18n: __deleteInstance(target)
    I18n->>I18n: remove from __instances
    Setup->>Comp: delete target.__VUE_I18N__
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing extra attention:
    • packages/vue-i18n-core/src/i18n.ts (many interdependent signature and lifecycle changes)
    • packages/vue-i18n-core/src/composer.ts and devtools.ts (public type surface and inspector wiring)
    • packages/vue-i18n-core/src/utils.ts and vue.d.ts (new exported util and type augmentation)
    • Test adjustments to ensure moved getCurrentInstance is exported and behaves identically in test contexts

Possibly related issues

  • Incompatibility with Vue Vapor #2234 — Adds GenericComponentInstance, widens instance unions, and moves/adjusts getCurrentInstance for Vue 3.6/Vapor compatibility; changes in this PR align with that objective.

Suggested labels

Type: Improvement

Poem

🐰 A tiny hop to newer days,
Instances stretched in gentle ways.
From vnode lairs to instance light,
i18n hops forward — swift and bright.
Alpha winds on Vue's new trail, we play! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.88% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "feat: compatible Vue3 vapor mode" is directly related to the primary objective and main changes of the PR. The changeset focuses on introducing support for Vue 3's vapor mode by introducing a new GenericComponentInstance type and updating the i18n library's public API to accept both traditional and vapor mode component instances. A developer reviewing the pull request history would clearly understand this PR addresses Vue 3 vapor mode compatibility, which aligns with the resolved issue #2234 and the stated objective to make vue-i18n work in Vue Vapor without errors.
✨ 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/vue-vapor3

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f4168dc and 2e2f7b2.

📒 Files selected for processing (1)
  • packages/vue-i18n-core/src/i18n.ts (8 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/vue-i18n-core/src/i18n.ts (1)
packages/vue-i18n-core/src/vue.d.ts (2)
  • ComponentInternalInstance (15-26)
  • GenericComponentInstance (28-39)
⏰ 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). (14)
  • GitHub Check: E2E test for rolldown build (macos-latest, 20)
  • GitHub Check: E2E test for rolldown build (macos-latest, 24)
  • GitHub Check: E2E test for rolldown build (ubuntu-latest, 20)
  • GitHub Check: E2E test for rolldown build (macos-latest, 22)
  • GitHub Check: E2E test for rolldown build (ubuntu-latest, 24)
  • GitHub Check: E2E test for rolldown build (ubuntu-latest, 22)
  • GitHub Check: Unit test (windows-latest, 20)
  • GitHub Check: Unit test (windows-latest, 24)
  • GitHub Check: Build (macos-latest, 24)
  • GitHub Check: Build (ubuntu-latest, 24)
  • GitHub Check: Build (windows-latest, 24)
  • GitHub Check: upload
  • GitHub Check: release
  • GitHub Check: release
🔇 Additional comments (3)
packages/vue-i18n-core/src/i18n.ts (3)

10-10: LGTM: Import changes support vapor mode compatibility.

The relocation of getCurrentInstance from Vue to utils and the addition of GenericComponentInstance type import are appropriate for vapor mode support. The utils module likely provides a vapor-compatible wrapper for getCurrentInstance.

Also applies to: 16-16, 21-27


144-156: LGTM: Type consistency issue from previous review has been resolved.

The runtime implementation now correctly uses ComponentInternalInstance | GenericComponentInstance union types throughout, matching the I18nInternal interface. The __instances Map and all related functions (__getInstance, __setInstance, __deleteInstance) consistently use the union type.

Also applies to: 323-340


645-646: LGTM: Devtools integration correctly adapted for vapor mode.

The change from vnode.el to target.__VUE_I18N__ is correct for vapor mode compatibility, since vapor doesn't use virtual nodes. Both ComponentInternalInstance and GenericComponentInstance define the __VUE_I18N__ property, ensuring this works across both modes.

Also applies to: 661-664


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 marked this pull request as ready for review October 26, 2025 16:03
@kazupon kazupon changed the title feat: support Vue3 vapor mode feat: compatible Vue3 vapor mode Oct 26, 2025
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: 1

🧹 Nitpick comments (2)
packages/vue-i18n-core/src/i18n.ts (2)

492-503: Harden instance shape assumptions for Vapor (avoid NPE, robust inject key).

Accessing instance.appContext.app can throw if Vapor’s instance shape differs. Use optional chaining and derive the injection key safely.

@@
-  if (
-    !instance.isCE &&
-    instance.appContext.app != null &&
-    !instance.appContext.app.__VUE_I18N_SYMBOL__
-  ) {
+  if (
+    !instance.isCE &&
+    (instance as any).appContext?.app &&
+    !(instance as any).appContext.app.__VUE_I18N_SYMBOL__
+  ) {
     throw createI18nError(I18nErrorCodes.NOT_INSTALLED)
   }
@@
-function getI18nInstance(instance: ComponentInternalInstance | GenericComponentInstance): I18n {
-  const i18n = inject(
-    !instance.isCE ? instance.appContext.app.__VUE_I18N_SYMBOL__! : I18nInjectionKey
-  )
+function getI18nInstance(instance: ComponentInternalInstance | GenericComponentInstance): I18n {
+  const appSymbol =
+    !instance.isCE ? (instance as any).appContext?.app?.__VUE_I18N_SYMBOL__ : undefined
+  const key = (appSymbol as InjectionKey<I18n> | undefined) ?? I18nInjectionKey
+  const i18n = inject(key)

Please run your Vapor e2e/tests that reproduce #2234 with <script setup vapor> to confirm no NPEs occur before inject and that NOT_INSTALLED still triggers as expected when the plugin isn’t provided.

Also applies to: 565-575


597-606: Parent traversal may differ in Vapor. Add safe accessors.

root, parent, and vnode.ctx might differ or be absent in Vapor. Guard with optional chaining to avoid crashes while walking up.

 function getComposer(
   i18n: I18n,
-  target: ComponentInternalInstance | GenericComponentInstance,
+  target: ComponentInternalInstance | GenericComponentInstance,
   useComponent = false
 ): Composer | null {
   let composer: Composer | null = null
-  const root = target.root
+  const root = (target as any).root
   let current: ComponentInternalInstance | GenericComponentInstance | null =
-    getParentComponentInstance(target, useComponent)
+    getParentComponentInstance(target, useComponent)
   while (current != null) {
     const i18nInternal = i18n as unknown as I18nInternal
     composer = i18nInternal.__getInstance(current)
 
     if (composer != null) {
       break
     }
-    if (root === current) {
+    if (root === current) {
       break
     }
-    current = current.parent
+    current = ((current as any).parent ?? null) as any
   }
   return composer
 }
 
 function getParentComponentInstance(
-  target: ComponentInternalInstance | GenericComponentInstance | null,
+  target: ComponentInternalInstance | GenericComponentInstance | null,
   useComponent = false
 ) {
   if (target == null) {
     return null
   }
   // if `useComponent: true` will be specified, we get lexical scope owner instance for use-case slots
-  return !useComponent ? target.parent : (target.vnode as any).ctx || target.parent // eslint-disable-line @typescript-eslint/no-explicit-any
+  return !useComponent
+    ? ((target as any).parent ?? null)
+    : ((target as any).vnode?.ctx) || (target as any).parent || null // eslint-disable-line @typescript-eslint/no-explicit-any
 }

Add/confirm a unit test under Vapor that exercises slot/lexical owner traversal (useComponent: true) to ensure parent resolution still finds the nearest composer.

Also applies to: 620-628

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 72f63b7 and f4168dc.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (9)
  • 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 (7 hunks)
  • packages/vue-i18n-core/src/utils.ts (3 hunks)
  • packages/vue-i18n-core/src/vue.d.ts (2 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)
🧰 Additional context used
🧬 Code graph analysis (4)
packages/vue-i18n-core/src/composer.ts (1)
packages/vue-i18n-core/src/vue.d.ts (2)
  • ComponentInternalInstance (15-26)
  • GenericComponentInstance (28-39)
packages/vue-i18n-core/src/utils.ts (1)
packages/vue-i18n-core/src/vue.d.ts (2)
  • ComponentInternalInstance (15-26)
  • GenericComponentInstance (28-39)
packages/vue-i18n-core/src/i18n.ts (1)
packages/vue-i18n-core/src/vue.d.ts (2)
  • ComponentInternalInstance (15-26)
  • GenericComponentInstance (28-39)
packages/vue-i18n-core/src/devtools.ts (2)
packages/vue-i18n-core/src/vue.d.ts (3)
  • App (7-10)
  • ComponentInternalInstance (15-26)
  • GenericComponentInstance (28-39)
packages/vue-i18n-core/src/i18n.ts (1)
  • global (389-391)
⏰ 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). (6)
  • GitHub Check: Build (ubuntu-latest, 24)
  • GitHub Check: Build (macos-latest, 24)
  • GitHub Check: Build (windows-latest, 24)
  • GitHub Check: release
  • GitHub Check: release
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (11)
package.json (1)

165-165: LGTM! Vue 3.6 alpha is required for Vapor mode support.

The upgrade to Vue 3.6.0-alpha.2 aligns with the PR objective to support Vue 3 Vapor mode. The alpha version is expected since Vapor is still experimental.

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

26-29: LGTM! Import relocation supports Vapor compatibility.

The getCurrentInstance import has been correctly relocated from Vue to the local utils module. This change aligns with the broader refactor to support Vue 3.6 Vapor mode via a unified instance accessor.

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

24-26: LGTM! Consistent with test refactoring.

The getCurrentInstance import relocation matches the pattern in other test files, maintaining consistency across the test suite.

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

19-19: LGTM! Instance-based tracking supports Vapor mode.

The changes correctly refactor devtools integration for Vapor compatibility:

  1. Type widening: Added GenericComponentInstance to support Vapor's component model
  2. Tracking shift: Replaced vnode.el.__VUE_I18N__ with componentInstance.__VUE_I18N__ for direct instance-based composer access
  3. Return types: Widened getComponentInstance to return both traditional and generic component instances

This approach is more robust for Vapor mode where vnode structures may differ from traditional Vue.

Also applies to: 64-65, 82-82, 137-139, 262-265

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

5-18: LGTM! Import reorganization for Vapor compatibility.

The updated imports correctly:

  • Add required fallbackWithLocaleChain and registerLocaleFallbacker from @intlify/core-base
  • Relocate getCurrentInstance to the utils module
  • Maintain proper type imports for web component testing

These changes align with the broader Vapor mode support refactor.

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

2-2: LGTM! New type enables Vapor mode support.

The introduction of GenericComponentInstance is the core type enabling Vapor compatibility:

  1. Parallel structure: Mirrors ComponentInternalInstance with isCE and __VUE_I18N__ properties
  2. Composer storage: Both interfaces store the i18n Composer instance via __VUE_I18N__
  3. Vapor compatibility: Allows the i18n system to work with both traditional Vue and Vapor component instances

This type augmentation properly extends Vue's module declarations for seamless integration.

Also applies to: 18-39

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

13-13: LGTM! Unified instance accessor for Vapor compatibility.

The changes create a compatibility layer for Vue 3.6 Vapor mode:

  1. Namespace import: import * as Vue enables accessing both currentInstance (Vapor) and getCurrentInstance() (traditional)
  2. Type widening: getComponentOptions now accepts both ComponentInternalInstance and GenericComponentInstance
  3. Unified accessor: The new getCurrentInstance() function checks Vue.currentInstance || Vue.getCurrentInstance() to work in both modes

The comment correctly notes this is for Vue 3.6 compatibility. This approach provides a single source of truth for obtaining the current component instance across Vapor and non-Vapor contexts.

Also applies to: 18-23, 163-165, 217-220

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

40-40: LGTM! Public API widened for Vapor compatibility.

The changes correctly extend the Composer API for Vapor mode:

  1. Import relocation: getCurrentInstance now sourced from utils for unified access across Vapor/non-Vapor
  2. Type extension: Added GenericComponentInstance to support Vapor's component model
  3. API signature: MissingHandler now accepts ComponentInternalInstance | GenericComponentInstance, allowing it to work with both traditional and Vapor components

This is a backward-compatible widening of the API that maintains existing functionality while adding Vapor support.

Also applies to: 52-58, 113-113, 228-233

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

21-27: No changes needed—module augmentation is correctly implemented.

The verification confirms that packages/vue-i18n-core/src/vue.d.ts properly augments the 'vue' module with the GenericComponentInstance interface (line 28) within a declare module 'vue' block and exports it correctly. The import in i18n.ts will resolve without errors.


641-642: DevTools storage migration to target.__VUE_I18N__ verified: no DOM-based storage detected.

Verification confirms:

  • No remnants of vnode.el.__VUE_I18N__ storage patterns
  • All usages are properly instance-based: target.__VUE_I18N__, componentInstance.__VUE_I18N__, instance.__VUE_I18N__
  • DevTools hooks correctly read from instance properties (devtools.ts lines 64-65, 137-139)
  • Proper cleanup in place (i18n.ts line 659: delete target.__VUE_I18N__)

10-10: Verification complete—no changes required.

The implementation already follows the correct Vapor compatibility pattern. The fallback Vue.currentInstance || Vue.getCurrentInstance() correctly attempts Vapor mode first, then falls back to classic Vue 3. Both modes provide ComponentInternalInstance with the required properties (appContext, root, parent), and the code includes defensive null checks (e.g., line 498 checks instance.appContext.app != null). No Vapor-specific issues were found in the codebase.

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.

1 participant