Repository: intlify/vue-i18n-next
Pull request #1832 (2024-04-30 10:08:33)

feat!: change `$t` overloaded signature for Legacy API mode
## feature (has breaking change)

In Vue I18n v9, it has a different interface from the Composition API mode and Legacy API mode of the `$t` overloaded signature.

Especially, `$t` signature in Legacy API mode has fewer overloaded signatures than in Composition API mode, as shown below:

| `$t` overloaded signatures                                                       | Legacy API v9 | Legacy API v10 | Composition API v9 & v10 |
| -------------------------------------------------------------------------------- | ------------- | -------------- | ------------------------ |
| `$t(key: Path): TranslateResult;`                                                | ✅            | ✅             | ✅                       |
| `$t(key: Path, locale: Locale): TranslateResult;`                                | ✅            | -              | -                        |
| `$t(key: Path, locale: Locale, list: unknown[]): TranslateResult;`               | ✅            | -              | -                        |
| `$t(key: Path, locale: Locale, named: NamedValue): TranslateResult;`             | ✅            | -              | -                        |
| `$t(key: Path, plural: number): TranslateResult;`                                | -             | ✅             | ✅                       |
| `$t(key: Path, plural: number, options: TranslateOptions): TranslateResult;`     | -             | ✅             | ✅                       |
| `$t(key: Path, defaultMsg: string): TranslateResult;`                            | -             | ✅             | ✅                       |
| `$t(key: Path, defaultMsg: string, options: TranslateOptions): TranslateResult;` | -             | ✅             | ✅                       |
| `$t(key: Path, list: unknown[]): TranslateResult;`                               | ✅            | ✅             | ✅                       |
| `$t(key: Path, list: unknown[], plural: number): TranslateResult;`               | -             | ✅             | ✅                       |
| `$t(key: Path, list: unknown[], defaultMsg: string): TranslateResult;`           | -             | ✅             | ✅                       |
| `$t(key: Path, list: unknown[], options: TranslateOptions): TranslateResult;`    | -             | ✅             | ✅                       |
| `$t(key: Path, named: Record<string, unknown>): TranslateResult;`                | ✅            | ✅             | ✅                       |
| `$t(key: Path, named: NamedValue, plural: number): TranslateResult;`             | -             | ✅             | ✅                       |
| `$t(key: Path, named: NamedValue, defaultMsg: string): TranslateResult;`         | -             | ✅             | ✅                       |
| `$t(key: Path, named: NamedValue, options: TranslateOptions): TranslateResult;`  | -             | ✅             | ✅                       |

Starting from v10, Legacy API mode can use the same `$t` overload signature as Composition API mode.

**Reason**: After that migration, when migrating to Composition API mode, we sometimes fall into a pitfall due to the different signature of `$t`.

cloudflare-pages[bot]: ## Deploying vue-i18n-next with &nbsp;<a href="https://pages.dev"><img alt="Cloudflare Pages" src="https://user-images.githubusercontent.com/23264/106598434-9e719e00-654f-11eb-9e59-6167043cfa01.png" width="16"></a> &nbsp;Cloudflare Pages

<table><tr><td><strong>Latest commit:</strong> </td><td>
<code>c573b1a</code>
</td></tr>
<tr><td><strong>Status:</strong></td><td>&nbsp;✅&nbsp; Deploy successful!</td></tr>
<tr><td><strong>Preview URL:</strong></td><td>
<a href='https://6f7126f0.vue-i18n-next.pages.dev'>https://6f7126f0.vue-i18n-next.pages.dev</a>
</td></tr>
<tr><td><strong>Branch Preview URL:</strong></td><td>
<a href='https://breaking-t-signature-legacy.vue-i18n-next.pages.dev'>https://breaking-t-signature-legacy.vue-i18n-next.pages.dev</a>
</td></tr>
</table>

[View logs](https://dash.cloudflare.com/?to=/:account/pages/view/vue-i18n-next/6f7126f0-be52-4091-9622-80c587040760)


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6442a665..7efb1b18 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -83,7 +83,7 @@ jobs:
     strategy:
       matrix:
         os: [ubuntu-latest, windows-latest, macos-latest]
-        node: [18.19, 20]
+        node: [18.19, 20, 22]
 
     runs-on: ${{ matrix.os }}
 
@@ -144,7 +144,7 @@ jobs:
     strategy:
       matrix:
         os: [ubuntu-latest, windows-latest, macos-latest]
-        node: [18.19, 20]
+        node: [18.19, 20, 22]
 
     runs-on: ${{ matrix.os }}
 
diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
index cb63e965..1bfd663c 100644
--- a/docs/.vitepress/config.mts
+++ b/docs/.vitepress/config.mts
@@ -195,11 +195,15 @@ function sidebarGuide() {
       collapsible: true,
       items: [
         {
-          text: 'Breaking Changes',
+          text: 'Breaking Changes in v9',
           link: '/guide/migration/breaking'
         },
         {
-          text: 'New Features',
+          text: 'Breaking Changes in v10',
+          link: '/guide/migration/breaking10'
+        },
+        {
+          text: 'New Features in v9',
           link: '/guide/migration/features'
         },
         {
diff --git a/docs/api/injection.md b/docs/api/injection.md
index 0301d5cb..15c271c8 100644
--- a/docs/api/injection.md
+++ b/docs/api/injection.md
@@ -90,6 +90,10 @@ Translation message
 
 ### $t(key, locale)
 
+:::danger NOTICE
+**This API signature is available in Legacy API mode only and is supported until v9**.
+:::
+
 Locale message translation
 
 **Signature:**
@@ -113,6 +117,10 @@ Translation message
 
 ### $t(key, locale, list)
 
+:::danger NOTICE
+**This API signature is available in Legacy API mode only and is supported until v9**.
+:::
+
 Locale message translation
 
 **Signature:**
@@ -137,6 +145,10 @@ Translation message
 
 ### $t(key, locale, named)
 
+:::danger NOTICE
+**This API signature is available in Legacy API mode only and is supported until v9**.
+:::
+
 Locale message translation
 
 **Signature:**
@@ -159,86 +171,17 @@ Overloaded `$t`. About details, see the [$t](injection#t-key) remarks.
 
 Translation message
 
-### $t(key, list)
-
-Locale message translation
-
-**Signature:**
-```typescript
-$t(key: Path, list: unknown[]): TranslateResult;
-```
-
-**Details**
-
-Overloaded `$t`. About details, see the [$t](injection#t-key) remarks.
-
-#### Parameters
-| Parameter | Type | Description |
-| --- | --- | --- |
-| key | Path | A target locale message key |
-| list | unknown[] | A values of list interpolation |
-
-#### Returns
-
-Translation message
-
-### $t(key, named)
-
-Locale message translation
-
-**Signature:**
-```typescript
-$t(key: Path, named: Record<string, unknown>): TranslateResult;
-```
-
-**Details**
-
-Overloaded `$t`. About details, see the [$t](injection#t-key) remarks.
-
-#### Parameters
-| Parameter | Type | Description |
-| --- | --- | --- |
-| key | Path | A target locale message key |
-| locale | Locale | A locale, override locale that global scope or local scope |
-| named | Record&lt;string, unknown&gt; | A values of named interpolation |
-
-#### Returns
-
-Translation message
-
-### $t(key)
-
-Locale message translation
-
-**Signature:**
-```typescript
-$t(key: Path): string;
-```
-
-**Details**
-
-Overloaded `$t`. About details, see the [$t](injection#t-key) remarks.
-
-#### Parameters
-| Parameter | Type | Description |
-| --- | --- | --- |
-| key | Path | A target locale message key |
-
-#### Returns
-
-Translation message
-
 ### $t(key, plural)
 
 Locale message translation
 
 **Signature:**
 ```typescript
-$t(key: Path, plural: number): string;
+$t(key: Path, plural: number): TranslateResult;
 ```
 
 :::tip NOTE
-Supported for **Composition API mode only**.
+Supported for **Composition API mode only until v9. v10 or later can also be used in Legacy API mode**.
 :::
 
 **Details**
@@ -261,11 +204,11 @@ Locale message translation
 
 **Signature:**
 ```typescript
-$t(key: Path, plural: number, options: TranslateOptions): string;
+$t(key: Path, plural: number, options: TranslateOptions): TranslateResult;
 ```
 
 :::tip NOTE
-Supported for **Composition API mode only**.
+Supported for **Composition API mode only until v9. v10 or later can also be used in Legacy API mode**.
 :::
 
 **Details**
@@ -289,11 +232,11 @@ Locale message translation
 
 **Signature:**
 ```typescript
-$t(key: Path, defaultMsg: string): string;
+$t(key: Path, defaultMsg: string): TranslateResult;
 ```
 
 :::tip NOTE
-Supported for **Composition API mode only**.
+Supported for **Composition API mode only until v9. v10 or later can also be used in Legacy API mode**.
 :::
 
 **Details**
@@ -316,11 +259,11 @@ Locale message translation
 
 **Signature:**
 ```typescript
-$t(key: Path, defaultMsg: string, options: TranslateOptions): string;
+$t(key: Path, defaultMsg: string, options: TranslateOptions): TranslateResult;
 ```
 
 :::tip NOTE
-Supported for **Composition API mode only**.
+Supported for **Composition API mode only until v9. v10 or later can also be used in Legacy API mode**.
 :::
 
 **Details**
@@ -344,7 +287,7 @@ Locale message translation
 
 **Signature:**
 ```typescript
-$t(key: Path, list: unknown[]): string;
+$t(key: Path, list: unknown[]): TranslateResult;
 ```
 
 **Details**
@@ -367,11 +310,11 @@ Locale message translation
 
 **Signature:**
 ```typescript
-$t(key: Path, list: unknown[], plural: number): string;
+$t(key: Path, list: unknown[], plural: number): TranslateResult;
 ```
 
 :::tip NOTE
-Supported for **Composition API mode only**.
+Supported for **Composition API mode only until v9. v10 or later can also be used in Legacy API mode**.
 :::
 
 **Details**
@@ -395,11 +338,11 @@ Locale message translation
 
 **Signature:**
 ```typescript
-$t(key: Path, list: unknown[], defaultMsg: string): string;
+$t(key: Path, list: unknown[], defaultMsg: string): TranslateResult;
 ```
 
 :::tip NOTE
-Supported for **Composition API mode only**.
+Supported for **Composition API mode only until v9. v10 or later can also be used in Legacy API mode**.
 :::
 
 **Details**
@@ -423,11 +366,11 @@ Locale message translation
 
 **Signature:**
 ```typescript
-$t(key: Path, list: unknown[], options: TranslateOptions): string;
+$t(key: Path, list: unknown[], options: TranslateOptions): TranslateResult;
 ```
 
 :::tip NOTE
-Supported for **Composition API mode only**.
+Supported for **Composition API mode only until v9. v10 or later can also be used in Legacy API mode**.
 :::
 
 **Details**
@@ -451,7 +394,7 @@ Locale message translation
 
 **Signature:**
 ```typescript
-$t(key: Path, named: NamedValue): string;
+$t(key: Path, named: NamedValue): TranslateResult;
 ```
 
 **Details**
@@ -474,11 +417,11 @@ Locale message translation
 
 **Signature:**
 ```typescript
-$t(key: Path, named: NamedValue, plural: number): string;
+$t(key: Path, named: NamedValue, plural: number): TranslateResult;
 ```
 
 :::tip NOTE
-Supported for **Composition API mode only**.
+Supported for **Composition API mode only until v9. v10 or later can also be used in Legacy API mode**.
 :::
 
 **Details**
@@ -502,11 +445,11 @@ Locale message translation
 
 **Signature:**
 ```typescript
-$t(key: Path, named: NamedValue, defaultMsg: string): string;
+$t(key: Path, named: NamedValue, defaultMsg: string): TranslateResult;
 ```
 
 :::tip NOTE
-Supported for **Composition API mode only**.
+Supported for **Composition API mode only until v9. v10 or later can also be used in Legacy API mode**.
 :::
 
 **Details**
@@ -530,11 +473,11 @@ Locale message translation
 
 **Signature:**
 ```typescript
-$t(key: Path, named: NamedValue, options: TranslateOptions): string;
+$t(key: Path, named: NamedValue, options: TranslateOptions): TranslateResult;
 ```
 
 :::tip NOTE
-Supported for **Composition API mode only**.
+Supported for **Composition API mode only until v9. v10 or later can also be used in Legacy API mode**.
 :::
 
 **Details**
diff --git a/docs/guide/migration/breaking.md b/docs/guide/migration/breaking.md
index 131904fe..630d7f2a 100644
--- a/docs/guide/migration/breaking.md
+++ b/docs/guide/migration/breaking.md
@@ -1,4 +1,4 @@
-# Breaking Changes
+# Breaking Changes in v9
 
 Most of the APIs offered in Vue I18n v9 (for Vue 3) strive to maintain compatibility, to ease the pain of migration from v8 (for Vue 2). But there are still a few breaking changes that you might encounter while migrating your application. This guide is how to adapt your application to make it work with Vue I18n v9.
 
diff --git a/docs/guide/migration/breaking10.md b/docs/guide/migration/breaking10.md
new file mode 100644
index 00000000..836cb45a
--- /dev/null
+++ b/docs/guide/migration/breaking10.md
@@ -0,0 +1,102 @@
+# Breaking Changes in v10
+
+:::warning NOTICE
+Vue I18n v10 **is still an alpha version**.
+:::
+
+## APIs
+
+### Change `$t` overloaded signature for Legacy API mode
+
+In Vue I18n v9, it has a different interface from the Composition API mode and Legacy API mode of the `$t` overloaded signature.
+
+Especially, `$t` signature in Legacy API mode has fewer overloaded signatures than in Composition API mode, as shown below:
+
+| `$t` overloaded signatures                                                       | Legacy API v9 | Legacy API v10 | Composition API v9 & v10 |
+| -------------------------------------------------------------------------------- | ------------- | -------------- | ------------------------ |
+| `$t(key: Path): TranslateResult;`                                                | ✅            | ✅             | ✅                       |
+| `$t(key: Path, locale: Locale): TranslateResult;`                                | ✅            | -              | -                        |
+| `$t(key: Path, locale: Locale, list: unknown[]): TranslateResult;`               | ✅            | -              | -                        |
+| `$t(key: Path, locale: Locale, named: NamedValue): TranslateResult;`             | ✅            | -              | -                        |
+| `$t(key: Path, plural: number): TranslateResult;`                                | -             | ✅             | ✅                       |
+| `$t(key: Path, plural: number, options: TranslateOptions): TranslateResult;`     | -             | ✅             | ✅                       |
+| `$t(key: Path, defaultMsg: string): TranslateResult;`                            | -             | ✅             | ✅                       |
+| `$t(key: Path, defaultMsg: string, options: TranslateOptions): TranslateResult;` | -             | ✅             | ✅                       |
+| `$t(key: Path, list: unknown[]): TranslateResult;`                               | ✅            | ✅             | ✅                       |
+| `$t(key: Path, list: unknown[], plural: number): TranslateResult;`               | -             | ✅             | ✅                       |
+| `$t(key: Path, list: unknown[], defaultMsg: string): TranslateResult;`           | -             | ✅             | ✅                       |
+| `$t(key: Path, list: unknown[], options: TranslateOptions): TranslateResult;`    | -             | ✅             | ✅                       |
+| `$t(key: Path, named: Record<string, unknown>): TranslateResult;`                | ✅            | ✅             | ✅                       |
+| `$t(key: Path, named: NamedValue, plural: number): TranslateResult;`             | -             | ✅             | ✅                       |
+| `$t(key: Path, named: NamedValue, defaultMsg: string): TranslateResult;`         | -             | ✅             | ✅                       |
+| `$t(key: Path, named: NamedValue, options: TranslateOptions): TranslateResult;`  | -             | ✅             | ✅                       |
+
+Starting from v10, Legacy API mode can use the same `$t` overload signature as Composition API mode.
+
+**Reason**: After that migration, when migrating to Composition API mode, we sometimes fall into a pitfall due to the different signature of `$t`.
+
+If you are using the following APIs in Legacy API mode, you must change to another signature because of the breaking changes:
+
+- `$t(key: Path, locale: Locale): TranslateResult;`
+- `$t(key: Path, locale: Locale, list: unknown[]): TranslateResult;`
+- `$t(key: Path, locale: Locale, named: NamedValue): TranslateResult;`
+
+#### `$t(key: Path, locale: Locale): TranslateResult;`
+
+Vue I18n v9.x:
+
+```vue
+<template>
+  <p>{{ $t('message.hello', 'ja') }}</p>
+</template>
+```
+
+Vue I18n v10 or later:
+
+use `$t(key: Path, list: unknown[], options: TranslateOptions): TranslateResult;` or `$t(key: Path, named: NamedValue, options: TranslateOptions): TranslateResult;`
+
+```vue
+<template>
+  <p>{{ $t('message.hello', {}, { locale: 'ja' }) }}</p>
+</template>
+```
+
+#### `$t(key: Path, locale: Locale, list: unknown[]): TranslateResult;`
+
+Vue I18n v9.x:
+
+```vue
+<template>
+  <p>{{ $t('message.hello', 'ja', ['dio']) }}</p>
+</template>
+```
+
+Vue I18n v10 or later:
+
+use `$t(key: Path, list: unknown[], options: TranslateOptions): TranslateResult;`
+
+```vue
+<template>
+  <p>{{ $t('message.hello', ['dio'], { locale: 'ja' }) }}</p>
+</template>
+```
+
+#### `$t(key: Path, locale: Locale, named: NamedValue): TranslateResult;`
+
+Vue I18n v9.x:
+
+```vue
+<template>
+  <p>{{ $t('message.hello', 'ja', { name: 'dio' }) }}</p>
+</template>
+```
+
+Vue I18n v10 or later:
+
+use `$t(key: Path, named: NamedValue, options: TranslateOptions): TranslateResult;`
+
+```vue
+<template>
+  <p>{{ $t('message.hello', { name: 'dio' }, { locale: 'ja' }) }}</p>
+</template>
+```
diff --git a/docs/guide/migration/features.md b/docs/guide/migration/features.md
index 3540e9f6..dc5f28ea 100644
--- a/docs/guide/migration/features.md
+++ b/docs/guide/migration/features.md
@@ -1,4 +1,4 @@
-# New Features
+# New Features in v9
 
 Vue I18n v9 offers not only Vue 3 support, but this version also is included new features.
 
diff --git a/examples/legacy/components/translation.html b/examples/legacy/components/translation.html
index b0369461..93fc0cc2 100644
--- a/examples/legacy/components/translation.html
+++ b/examples/legacy/components/translation.html
@@ -19,7 +19,9 @@
 
       <h2>localize with DOM contents:</h2>
       <i18n-t tag="p" class="list" keypath="message.list" locale="en">
-        <span class="lang">{{ $t('message.language','en') }}</span>
+        <span class="lang"
+          >{{ $t('message.language', [], { locale: 'en' }) }}</span
+        >
       </i18n-t>
 
       <h2>localize with using linked:</h2>
@@ -31,7 +33,9 @@
 
       <h2>localize with using plural:</h2>
       <form>
-        <label for="locale-select">{{ $t('message.quantity', 'en') }}</label>
+        <label for="locale-select"
+          >{{ $t('message.quantity', {}, { locale: 'en' }) }}</label
+        >
         <select id="locale-select" v-model="count">
           <option value="0">0</option>
           <option value="1">1</option>
diff --git a/packages/petite-vue-i18n/src/vue.d.ts b/packages/petite-vue-i18n/src/vue.d.ts
index 36cf8167..c4d1b744 100644
--- a/packages/petite-vue-i18n/src/vue.d.ts
+++ b/packages/petite-vue-i18n/src/vue.d.ts
@@ -101,157 +101,6 @@ declare module '@vue/runtime-core' {
     >(
       key: Key | ResourceKeys | Path
     ): TranslateResult
-    /**
-     * Locale message translation
-     *
-     * @remarks
-     * Overloaded `$t`. About details, see the {@link $t} remarks.
-     *
-     * @param key -  A target locale message key
-     * @param locale - A locale, override locale that global scope or local scope
-     *
-     * @returns translation message
-     */
-    $t<
-      Key extends string,
-      DefinedLocaleMessage extends
-        RemovedIndexResources<DefineLocaleMessage> = RemovedIndexResources<DefineLocaleMessage>,
-      Keys = IsEmptyObject<DefinedLocaleMessage> extends false
-        ? PickupPaths<{
-            [K in keyof DefinedLocaleMessage]: DefinedLocaleMessage[K]
-          }>
-        : never,
-      ResourceKeys extends Keys = IsNever<Keys> extends false ? Keys : never
-    >(
-      key: Key | ResourceKeys | Path
-    ): TranslateResult
-    /**
-     * Locale message translation
-     *
-     * @remarks
-     * Overloaded `$t`. About details, see the {@link $t} remarks.
-     *
-     * @param key - A target locale message key
-     * @param locale - A locale, override locale that global scope or local scope
-     * @param list - A values of list interpolation
-     *
-     * @returns translation message
-     */
-    $t<
-      Key extends string,
-      DefinedLocaleMessage extends
-        RemovedIndexResources<DefineLocaleMessage> = RemovedIndexResources<DefineLocaleMessage>,
-      Keys = IsEmptyObject<DefinedLocaleMessage> extends false
-        ? PickupPaths<{
-            [K in keyof DefinedLocaleMessage]: DefinedLocaleMessage[K]
-          }>
-        : never,
-      ResourceKeys extends Keys = IsNever<Keys> extends false ? Keys : never
-    >(
-      key: Key | ResourceKeys | Path,
-      locale: Locale,
-      list: unknown[]
-    ): TranslateResult
-    /**
-     * Locale message translation
-     *
-     * @remarks
-     * Overloaded `$t`. About details, see the {@link $t} remarks.
-     *
-     * @param key - A target locale message key
-     * @param locale - A locale, override locale that global scope or local scope
-     * @param named - A values of named interpolation
-     *
-     * @returns translation message
-     */
-    $t<
-      Key extends string,
-      DefinedLocaleMessage extends
-        RemovedIndexResources<DefineLocaleMessage> = RemovedIndexResources<DefineLocaleMessage>,
-      Keys = IsEmptyObject<DefinedLocaleMessage> extends false
-        ? PickupPaths<{
-            [K in keyof DefinedLocaleMessage]: DefinedLocaleMessage[K]
-          }>
-        : never,
-      ResourceKeys extends Keys = IsNever<Keys> extends false ? Keys : never
-    >(
-      key: Key | ResourceKeys | Path,
-      locale: Locale,
-      named: object
-    ): TranslateResult
-    /**
-     * Locale message translation
-     *
-     * @remarks
-     * Overloaded `$t`. About details, see the {@link $t} remarks.
-     *
-     * @param key - A target locale message key
-     * @param list - A values of list interpolation
-     *
-     * @returns translation message
-     */
-    $t<
-      Key extends string,
-      DefinedLocaleMessage extends
-        RemovedIndexResources<DefineLocaleMessage> = RemovedIndexResources<DefineLocaleMessage>,
-      Keys = IsEmptyObject<DefinedLocaleMessage> extends false
-        ? PickupPaths<{
-            [K in keyof DefinedLocaleMessage]: DefinedLocaleMessage[K]
-          }>
-        : never,
-      ResourceKeys extends Keys = IsNever<Keys> extends false ? Keys : never
-    >(
-      key: Key | ResourceKeys | Path,
-      list: unknown[]
-    ): TranslateResult
-    /**
-     * Locale message translation
-     *
-     * @remarks
-     * Overloaded `$t`. About details, see the {@link $t} remarks.
-     *
-     * @param key - A target locale message key
-     * @param named - A values of named interpolation
-     *
-     * @returns translation message
-     */
-    $t<
-      Key extends string,
-      DefinedLocaleMessage extends
-        RemovedIndexResources<DefineLocaleMessage> = RemovedIndexResources<DefineLocaleMessage>,
-      Keys = IsEmptyObject<DefinedLocaleMessage> extends false
-        ? PickupPaths<{
-            [K in keyof DefinedLocaleMessage]: DefinedLocaleMessage[K]
-          }>
-        : never,
-      ResourceKeys extends Keys = IsNever<Keys> extends false ? Keys : never
-    >(
-      key: Key | ResourceKeys | Path,
-      named: Record<string, unknown>
-    ): TranslateResult
-    /**
-     * Locale message translation
-     *
-     * @remarks
-     * Overloaded `$t`. About details, see the {@link $t} remarks.
-     *
-     * @param key - A target locale message key
-     *
-     * @returns translation message
-     */
-    $t<
-      Key extends string,
-      DefinedLocaleMessage extends
-        RemovedIndexResources<DefineLocaleMessage> = RemovedIndexResources<DefineLocaleMessage>,
-      Keys = IsEmptyObject<DefinedLocaleMessage> extends false
-        ? PickupPaths<{
-            [K in keyof DefinedLocaleMessage]: DefinedLocaleMessage[K]
-          }>
-        : never,
-      ResourceKeys extends Keys = IsNever<Keys> extends false ? Keys : never
-    >(
-      key: Key | ResourceKeys | Path
-    ): string
     /**
      * Locale message translation
      *
@@ -276,7 +125,7 @@ declare module '@vue/runtime-core' {
     >(
       key: Key | ResourceKeys | Path,
       plural: number
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -303,7 +152,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       plural: number,
       options: TranslateOptions
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -328,7 +177,7 @@ declare module '@vue/runtime-core' {
     >(
       key: Key | ResourceKeys | Path,
       defaultMsg: string
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -355,7 +204,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       defaultMsg: string,
       options: TranslateOptions
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -380,7 +229,7 @@ declare module '@vue/runtime-core' {
     >(
       key: Key | ResourceKeys | Path,
       list: unknown[]
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -407,7 +256,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       list: unknown[],
       plural: number
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -461,7 +310,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       list: unknown[],
       options: TranslateOptions
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -486,7 +335,7 @@ declare module '@vue/runtime-core' {
     >(
       key: Key | ResourceKeys | Path,
       named: NamedValue
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -513,7 +362,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       named: NamedValue,
       plural: number
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -540,7 +389,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       named: NamedValue,
       defaultMsg: string
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -567,7 +416,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       named: NamedValue,
       options: TranslateOptions
-    ): string
+    ): TranslateResult
     /**
      * Resolve locale message translation
      *
diff --git a/packages/vue-i18n-core/src/legacy.ts b/packages/vue-i18n-core/src/legacy.ts
index b3b133a5..22d9bf80 100644
--- a/packages/vue-i18n-core/src/legacy.ts
+++ b/packages/vue-i18n-core/src/legacy.ts
@@ -1537,38 +1537,10 @@ export function createVueI18n(options: any = {}): any {
 
     // t
     t(...args: unknown[]): TranslateResult {
-      const [arg1, arg2, arg3] = args
-      const options = {} as TranslateOptions
-      let list: unknown[] | null = null
-      let named: NamedValue | null = null
-
-      if (!isString(arg1)) {
-        throw createI18nError(I18nErrorCodes.INVALID_ARGUMENT)
-      }
-      const key = arg1
-
-      if (isString(arg2)) {
-        options.locale = arg2
-      } else if (isArray(arg2)) {
-        list = arg2
-      } else if (isPlainObject(arg2)) {
-        named = arg2 as NamedValue
-      }
-
-      if (isArray(arg3)) {
-        list = arg3
-      } else if (isPlainObject(arg3)) {
-        named = arg3 as NamedValue
-      }
-
-      // return composer.t(key, (list || named || {}) as any, options)
-      return Reflect.apply(composer.t, composer, [
-        key,
-        (list || named || {}) as any,
-        options
-      ])
+      return Reflect.apply(composer.t, composer, [...args])
     },
 
+    // rt
     rt(...args: unknown[]): TranslateResult {
       return Reflect.apply(composer.rt, composer, [...args])
     },
diff --git a/packages/vue-i18n/src/vue.d.ts b/packages/vue-i18n/src/vue.d.ts
index abc72790..88ec73ed 100644
--- a/packages/vue-i18n/src/vue.d.ts
+++ b/packages/vue-i18n/src/vue.d.ts
@@ -106,157 +106,6 @@ declare module '@vue/runtime-core' {
     >(
       key: Key | ResourceKeys | Path
     ): TranslateResult
-    /**
-     * Locale message translation
-     *
-     * @remarks
-     * Overloaded `$t`. About details, see the {@link $t} remarks.
-     *
-     * @param key -  A target locale message key
-     * @param locale - A locale, override locale that global scope or local scope
-     *
-     * @returns translation message
-     */
-    $t<
-      Key extends string,
-      DefinedLocaleMessage extends
-        RemovedIndexResources<DefineLocaleMessage> = RemovedIndexResources<DefineLocaleMessage>,
-      Keys = IsEmptyObject<DefinedLocaleMessage> extends false
-        ? PickupPaths<{
-            [K in keyof DefinedLocaleMessage]: DefinedLocaleMessage[K]
-          }>
-        : never,
-      ResourceKeys extends Keys = IsNever<Keys> extends false ? Keys : never
-    >(
-      key: Key | ResourceKeys | Path
-    ): TranslateResult
-    /**
-     * Locale message translation
-     *
-     * @remarks
-     * Overloaded `$t`. About details, see the {@link $t} remarks.
-     *
-     * @param key - A target locale message key
-     * @param locale - A locale, override locale that global scope or local scope
-     * @param list - A values of list interpolation
-     *
-     * @returns translation message
-     */
-    $t<
-      Key extends string,
-      DefinedLocaleMessage extends
-        RemovedIndexResources<DefineLocaleMessage> = RemovedIndexResources<DefineLocaleMessage>,
-      Keys = IsEmptyObject<DefinedLocaleMessage> extends false
-        ? PickupPaths<{
-            [K in keyof DefinedLocaleMessage]: DefinedLocaleMessage[K]
-          }>
-        : never,
-      ResourceKeys extends Keys = IsNever<Keys> extends false ? Keys : never
-    >(
-      key: Key | ResourceKeys | Path,
-      locale: Locale,
-      list: unknown[]
-    ): TranslateResult
-    /**
-     * Locale message translation
-     *
-     * @remarks
-     * Overloaded `$t`. About details, see the {@link $t} remarks.
-     *
-     * @param key - A target locale message key
-     * @param locale - A locale, override locale that global scope or local scope
-     * @param named - A values of named interpolation
-     *
-     * @returns translation message
-     */
-    $t<
-      Key extends string,
-      DefinedLocaleMessage extends
-        RemovedIndexResources<DefineLocaleMessage> = RemovedIndexResources<DefineLocaleMessage>,
-      Keys = IsEmptyObject<DefinedLocaleMessage> extends false
-        ? PickupPaths<{
-            [K in keyof DefinedLocaleMessage]: DefinedLocaleMessage[K]
-          }>
-        : never,
-      ResourceKeys extends Keys = IsNever<Keys> extends false ? Keys : never
-    >(
-      key: Key | ResourceKeys | Path,
-      locale: Locale,
-      named: object
-    ): TranslateResult
-    /**
-     * Locale message translation
-     *
-     * @remarks
-     * Overloaded `$t`. About details, see the {@link $t} remarks.
-     *
-     * @param key - A target locale message key
-     * @param list - A values of list interpolation
-     *
-     * @returns translation message
-     */
-    $t<
-      Key extends string,
-      DefinedLocaleMessage extends
-        RemovedIndexResources<DefineLocaleMessage> = RemovedIndexResources<DefineLocaleMessage>,
-      Keys = IsEmptyObject<DefinedLocaleMessage> extends false
-        ? PickupPaths<{
-            [K in keyof DefinedLocaleMessage]: DefinedLocaleMessage[K]
-          }>
-        : never,
-      ResourceKeys extends Keys = IsNever<Keys> extends false ? Keys : never
-    >(
-      key: Key | ResourceKeys | Path,
-      list: unknown[]
-    ): TranslateResult
-    /**
-     * Locale message translation
-     *
-     * @remarks
-     * Overloaded `$t`. About details, see the {@link $t} remarks.
-     *
-     * @param key - A target locale message key
-     * @param named - A values of named interpolation
-     *
-     * @returns translation message
-     */
-    $t<
-      Key extends string,
-      DefinedLocaleMessage extends
-        RemovedIndexResources<DefineLocaleMessage> = RemovedIndexResources<DefineLocaleMessage>,
-      Keys = IsEmptyObject<DefinedLocaleMessage> extends false
-        ? PickupPaths<{
-            [K in keyof DefinedLocaleMessage]: DefinedLocaleMessage[K]
-          }>
-        : never,
-      ResourceKeys extends Keys = IsNever<Keys> extends false ? Keys : never
-    >(
-      key: Key | ResourceKeys | Path,
-      named: Record<string, unknown>
-    ): TranslateResult
-    /**
-     * Locale message translation
-     *
-     * @remarks
-     * Overloaded `$t`. About details, see the {@link $t} remarks.
-     *
-     * @param key - A target locale message key
-     *
-     * @returns translation message
-     */
-    $t<
-      Key extends string,
-      DefinedLocaleMessage extends
-        RemovedIndexResources<DefineLocaleMessage> = RemovedIndexResources<DefineLocaleMessage>,
-      Keys = IsEmptyObject<DefinedLocaleMessage> extends false
-        ? PickupPaths<{
-            [K in keyof DefinedLocaleMessage]: DefinedLocaleMessage[K]
-          }>
-        : never,
-      ResourceKeys extends Keys = IsNever<Keys> extends false ? Keys : never
-    >(
-      key: Key | ResourceKeys | Path
-    ): string
     /**
      * Locale message translation
      *
@@ -281,7 +130,7 @@ declare module '@vue/runtime-core' {
     >(
       key: Key | ResourceKeys | Path,
       plural: number
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -308,7 +157,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       plural: number,
       options: TranslateOptions
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -333,7 +182,7 @@ declare module '@vue/runtime-core' {
     >(
       key: Key | ResourceKeys | Path,
       defaultMsg: string
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -360,7 +209,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       defaultMsg: string,
       options: TranslateOptions
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -385,7 +234,7 @@ declare module '@vue/runtime-core' {
     >(
       key: Key | ResourceKeys | Path,
       list: unknown[]
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -412,7 +261,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       list: unknown[],
       plural: number
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -439,7 +288,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       list: unknown[],
       defaultMsg: string
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -466,7 +315,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       list: unknown[],
       options: TranslateOptions
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -491,7 +340,7 @@ declare module '@vue/runtime-core' {
     >(
       key: Key | ResourceKeys | Path,
       named: NamedValue
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -518,7 +367,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       named: NamedValue,
       plural: number
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -545,7 +394,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       named: NamedValue,
       defaultMsg: string
-    ): string
+    ): TranslateResult
     /**
      * Locale message translation
      *
@@ -572,7 +421,7 @@ declare module '@vue/runtime-core' {
       key: Key | ResourceKeys | Path,
       named: NamedValue,
       options: TranslateOptions
-    ): string
+    ): TranslateResult
     /**
      * Resolve locale message translation
      *


Test patch:
diff --git a/packages/vue-i18n-core/test/i18n.test.ts b/packages/vue-i18n-core/test/i18n.test.ts
index 05f47fd4..2571277d 100644
--- a/packages/vue-i18n-core/test/i18n.test.ts
+++ b/packages/vue-i18n-core/test/i18n.test.ts
@@ -2,6 +2,16 @@
  * @vitest-environment jsdom
  */
 
+// utils
+import * as shared from '@intlify/shared'
+vi.mock('@intlify/shared', async () => {
+  const actual = await vi.importActual<object>('@intlify/shared')
+  return {
+    ...actual,
+    warn: vi.fn()
+  }
+})
+
 import {
   h,
   ref,
@@ -1358,3 +1368,92 @@ describe('Composer & VueI18n extend hooking', () => {
     expect(vueI18nDisposeSpy).toHaveBeenCalledTimes(2)
   })
 })
+
+describe('component injections', () => {
+  const mockWarn = vi.spyOn(shared, 'warn')
+  // eslint-disable-next-line @typescript-eslint/no-empty-function
+  mockWarn.mockImplementation(() => {})
+
+  const messages = {
+    en: {
+      hello: 'hello world!',
+      list: 'hello, {0}!',
+      named: 'hello, {name}!',
+      plural: 'no apples | one apple | {count} apples'
+    },
+    ja: {
+      hello: 'こんにちは、世界！',
+      list: 'こんにちは、{0}！',
+      named: 'こんにちは、{name}！',
+      plural: 'りんご無い | りんご1個 | りんご{count}個'
+    }
+  }
+
+  test('composition mode', async () => {
+    const i18n = createI18n({
+      legacy: false,
+      locale: 'en',
+      messages
+    })
+    const App = defineComponent({
+      setup() {
+        useI18n()
+        return {}
+      },
+      template: `<div>
+<p>{{ $t('hello') }}</p>
+<p>{{ $t('list', ['world']) }}</p>
+<p>{{ $t('named', { name: 'world' }) }}</p>
+<p>{{ $t('plural', 0) }}</p>
+<p>{{ $t('plural', 1, { locale: 'ja' }) }}</p>
+<p>{{ $t('default', 'default message') }}</p>
+<p>{{ $t('default', 'default {msg}', { named: { msg: 'msg' } }) }}</p>
+<p>{{ $t('plural', ['many'], 4) }}</p>
+<p>{{ $t('default', ['list msg'], 'default {0}') }}</p>
+<p>{{ $t('list', ['世界'], { locale: 'ja' }) }}</p>
+<p>{{ $t('plural', { count: 'many' }, 4) }}</p>
+<p>{{ $t('default', { msg: 'named msg' }, 'default {msg}') }}</p>
+<p>{{ $t('named', { name: '世界' }, { locale: 'ja' }) }}</p>
+<p>{{ $t('hello', {}, { locale: 'en' }) }}</p>
+<p>{{ $t('hello', [], { locale: 'ja' }) }}</p>
+</div>`
+    })
+    const wrapper = await mount(App, i18n)
+
+    expect(wrapper.html()).toEqual(
+      '<div><p>hello world!</p><p>hello, world!</p><p>hello, world!</p><p>no apples</p><p>りんご1個</p><p>default message</p><p>default msg</p><p>4 apples</p><p>default list msg</p><p>こんにちは、世界！</p><p>many apples</p><p>default named msg</p><p>こんにちは、世界！</p><p>hello world!</p><p>こんにちは、世界！</p></div>'
+    )
+  })
+
+  test('legacy mode', async () => {
+    const i18n = createI18n({
+      legacy: true,
+      locale: 'en',
+      messages
+    })
+    const App = defineComponent({
+      template: `<div>
+<p>{{ $t('hello') }}</p>
+<p>{{ $t('list', ['world']) }}</p>
+<p>{{ $t('named', { name: 'world' }) }}</p>
+<p>{{ $t('plural', 0) }}</p>
+<p>{{ $t('plural', 1, { locale: 'ja' }) }}</p>
+<p>{{ $t('default', 'default message') }}</p>
+<p>{{ $t('default', 'default {msg}', { named: { msg: 'msg' } }) }}</p>
+<p>{{ $t('plural', ['many'], 4) }}</p>
+<p>{{ $t('default', ['list msg'], 'default {0}') }}</p>
+<p>{{ $t('list', ['世界'], { locale: 'ja' }) }}</p>
+<p>{{ $t('plural', { count: 'many' }, 4) }}</p>
+<p>{{ $t('default', { msg: 'named msg' }, 'default {msg}') }}</p>
+<p>{{ $t('named', { name: '世界' }, { locale: 'ja' }) }}</p>
+<p>{{ $t('hello', {}, { locale: 'en' }) }}</p>
+<p>{{ $t('hello', [], { locale: 'ja' }) }}</p>
+</div>`
+    })
+    const wrapper = await mount(App, i18n)
+
+    expect(wrapper.html()).toEqual(
+      '<div><p>hello world!</p><p>hello, world!</p><p>hello, world!</p><p>no apples</p><p>りんご1個</p><p>default message</p><p>default msg</p><p>4 apples</p><p>default list msg</p><p>こんにちは、世界！</p><p>many apples</p><p>default named msg</p><p>こんにちは、世界！</p><p>hello world!</p><p>こんにちは、世界！</p></div>'
+    )
+  })
+})
diff --git a/packages/vue-i18n-core/test/legacy.test.ts b/packages/vue-i18n-core/test/legacy.test.ts
index 052e0f6e..1c143623 100644
--- a/packages/vue-i18n-core/test/legacy.test.ts
+++ b/packages/vue-i18n-core/test/legacy.test.ts
@@ -176,25 +176,6 @@ describe('t', () => {
     expect(i18n.t('morning', ['kazupon'])).toEqual('good morning kazupon')
     expect(i18n.t('linked')).toEqual('hi KAZUPON')
   })
-
-  test(errorMessages[I18nErrorCodes.INVALID_ARGUMENT], () => {
-    const i18n = createVueI18n({
-      locale: 'en',
-      messages: {
-        en: {
-          name: 'kazupon',
-          hello: 'Hello!',
-          hi: 'hi {name}!',
-          morning: 'good morning {0}',
-          linked: 'hi @.upper:name'
-        }
-      }
-    })
-
-    expect(() => {
-      i18n.t(4 as any) // eslint-disable-line @typescript-eslint/no-explicit-any
-    }).toThrowError(errorMessages[I18nErrorCodes.INVALID_ARGUMENT])
-  })
 })
 
 describe('rt', () => {