Repository: intlify/eslint-plugin-vue-i18n
Pull request #557 (2024-10-06 10:11:41)

fix(deps): update dependency @intlify/message-compiler to v10
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@intlify/message-compiler](https://redirect.github.com/intlify/vue-i18n/tree/master/packages/message-compiler#readme) ([source](https://redirect.github.com/intlify/vue-i18n/tree/HEAD/packages/message-compiler)) | [`^9.12.0` -> `^10.0.0`](https://renovatebot.com/diffs/npm/@intlify%2fmessage-compiler/9.12.0/10.0.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@intlify%2fmessage-compiler/10.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@intlify%2fmessage-compiler/10.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@intlify%2fmessage-compiler/9.12.0/10.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@intlify%2fmessage-compiler/9.12.0/10.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>intlify/vue-i18n (@&#8203;intlify/message-compiler)</summary>

### [`v10.0.5`](https://redirect.github.com/intlify/vue-i18n/releases/tag/v10.0.5)

[Compare Source](https://redirect.github.com/intlify/vue-i18n/compare/v10.0.4...v10.0.5)

<!-- Release notes generated using configuration in .github/release.yml at v10.0.5 -->

##### What's Changed

##### 🔒 Security Fixes

-   fix: XSS vulnerability with prototype pollution on AST: https://github.com/intlify/vue-i18n/security/advisories/GHSA-9r9m-ffp6-9x4v
-   fix: prototype pollusion on deepCopy: https://github.com/intlify/vue-i18n/security/advisories/GHSA-hjwq-mjwj-4x6c

**Full Changelog**: https://github.com/intlify/vue-i18n/compare/v10.0.4...v10.0.5

### [`v10.0.4`](https://redirect.github.com/intlify/vue-i18n/blob/HEAD/CHANGELOG.md#v1004-2024-10-06T074231Z)

[Compare Source](https://redirect.github.com/intlify/vue-i18n/compare/v10.0.3...v10.0.4)

This changelog is generated by [GitHub Releases](https://redirect.github.com/intlify/vue-i18n/releases/tag/v10.0.4)

<!-- Release notes generated using configuration in .github/release.yml at v10.0.4 -->

#### What's Changed

##### 🐛 Bug Fixes

-   fix: cannot resolve empty string on plural by [@&#8203;kazupon](https://redirect.github.com/kazupon) in [https://github.com/intlify/vue-i18n/pull/1985](https://redirect.github.com/intlify/vue-i18n/pull/1985)

##### 📝️ Documentations

-   Add petite-vue-i18n package to README by [@&#8203;vikingair](https://redirect.github.com/vikingair) in [https://github.com/intlify/vue-i18n/pull/1971](https://redirect.github.com/intlify/vue-i18n/pull/1971)

#### New Contributors

-   [@&#8203;vikingair](https://redirect.github.com/vikingair) made their first contribution in [https://github.com/intlify/vue-i18n/pull/1971](https://redirect.github.com/intlify/vue-i18n/pull/1971)

**Full Changelog**: https://github.com/intlify/vue-i18n/compare/v10.0.3...v10.0.4

### [`v10.0.3`](https://redirect.github.com/intlify/vue-i18n/blob/HEAD/CHANGELOG.md#v1003-2024-09-22T110922Z)

[Compare Source](https://redirect.github.com/intlify/vue-i18n/compare/v10.0.2...v10.0.3)

This changelog is generated by [GitHub Releases](https://redirect.github.com/intlify/vue-i18n/releases/tag/v10.0.3)

<!-- Release notes generated using configuration in .github/release.yml at v10.0.3 -->

#### What's Changed

##### 🐛 Bug Fixes

-   fix(petite-vue-i18n): cannot register correctly message resolver and locale fallbacker by [@&#8203;kazupon](https://redirect.github.com/kazupon) in [https://github.com/intlify/vue-i18n/pull/1967](https://redirect.github.com/intlify/vue-i18n/pull/1967)

##### 📝️ Documentations

-   docs: add unplugin-vue-i18n setting for petite-vue-i18n by [@&#8203;kazupon](https://redirect.github.com/kazupon) in [https://github.com/intlify/vue-i18n/pull/1968](https://redirect.github.com/intlify/vue-i18n/pull/1968)

**Full Changelog**: https://github.com/intlify/vue-i18n/compare/v10.0.2...v10.0.3

### [`v10.0.2`](https://redirect.github.com/intlify/vue-i18n/blob/HEAD/CHANGELOG.md#v1002-2024-09-21T180606Z)

[Compare Source](https://redirect.github.com/intlify/vue-i18n/compare/v10.0.1...v10.0.2)

This changelog is generated by [GitHub Releases](https://redirect.github.com/intlify/vue-i18n/releases/tag/v10.0.2)

<!-- Release notes generated using configuration in .github/release.yml at v10.0.2 -->

#### What's Changed

##### ⚡ Improvement Features

-   fix: revert [#&#8203;1379](https://redirect.github.com/intlify/vue-i18n/issues/1379) by [@&#8203;BobbieGoede](https://redirect.github.com/BobbieGoede) in [https://github.com/intlify/vue-i18n/pull/1953](https://redirect.github.com/intlify/vue-i18n/pull/1953)
-   fix: messages `deepCopy` mutates `src` arguments by [@&#8203;BobbieGoede](https://redirect.github.com/BobbieGoede) in [https://github.com/intlify/vue-i18n/pull/1947](https://redirect.github.com/intlify/vue-i18n/pull/1947)

##### 📝️ Documentations

-   docs: add team members by [@&#8203;kazupon](https://redirect.github.com/kazupon) in [https://github.com/intlify/vue-i18n/pull/1951](https://redirect.github.com/intlify/vue-i18n/pull/1951)
-   docs: add how to use shared locale messages on composition api by [@&#8203;kazupon](https://redirect.github.com/kazupon) in [https://github.com/intlify/vue-i18n/pull/1964](https://redirect.github.com/intlify/vue-i18n/pull/1964)

**Full Changelog**: https://github.com/intlify/vue-i18n/compare/v10.0.1...v10.0.2

### [`v10.0.1`](https://redirect.github.com/intlify/vue-i18n/blob/HEAD/CHANGELOG.md#v1001-2024-09-12T053356Z)

[Compare Source](https://redirect.github.com/intlify/vue-i18n/compare/v10.0.0...v10.0.1)

This changelog is generated by [GitHub Releases](https://redirect.github.com/intlify/vue-i18n/releases/tag/v10.0.1)

<!-- Release notes generated using configuration in .github/release.yml at v10.0.1 -->

#### What's Changed

##### 🐛 Bug Fixes

-   fix: petite-vue-i18n type errors by [@&#8203;TPORL](https://redirect.github.com/TPORL) in [https://github.com/intlify/vue-i18n/pull/1945](https://redirect.github.com/intlify/vue-i18n/pull/1945)

#### New Contributors

-   [@&#8203;TPORL](https://redirect.github.com/TPORL) made their first contribution in [https://github.com/intlify/vue-i18n/pull/1945](https://redirect.github.com/intlify/vue-i18n/pull/1945)

**Full Changelog**: https://github.com/intlify/vue-i18n/compare/v10.0.0...v10.0.1

### [`v10.0.0`](https://redirect.github.com/intlify/vue-i18n/blob/HEAD/CHANGELOG.md#v1000-2024-09-10T044141Z)

[Compare Source](https://redirect.github.com/intlify/vue-i18n/compare/v9.14.2...v10.0.0)

We are excited to announce the release of Vue I18n v10.
We had many contributors.

Thanks for your contributing ❤️

### [`v9.14.2`](https://redirect.github.com/intlify/vue-i18n/releases/tag/v9.14.2)

[Compare Source](https://redirect.github.com/intlify/vue-i18n/compare/v9.14.1...v9.14.2)

<!-- Release notes generated using configuration in .github/release.yml at v9.14.2 -->

#### What's Changed

##### 🔒 Security Fixes

-   fix: XSS vulnerability with prototype pollution on AST: https://github.com/intlify/vue-i18n/security/advisories/GHSA-9r9m-ffp6-9x4v
-   fix: prototype pollusion on deepCopy: https://github.com/intlify/vue-i18n/security/advisories/GHSA-hjwq-mjwj-4x6c

**Full Changelog**: https://github.com/intlify/vue-i18n/compare/v9.14.1...v9.14.2

### [`v9.14.1`](https://redirect.github.com/intlify/vue-i18n/releases/tag/v9.14.1)

[Compare Source](https://redirect.github.com/intlify/vue-i18n/compare/v9.14.0...v9.14.1)

<!-- Release notes generated using configuration in .github/release.yml at v9.14.1 -->

#### What's Changed

##### 🐛 Bug Fixes

-   fix: messages `deepCopy` mutates `src` arguments  by [@&#8203;BobbieGoede](https://redirect.github.com/BobbieGoede) in [https://github.com/intlify/vue-i18n/pull/1975](https://redirect.github.com/intlify/vue-i18n/pull/1975)

**Full Changelog**: https://github.com/intlify/vue-i18n/compare/v9.14.0...v9.14.1

### [`v9.14.0`](https://redirect.github.com/intlify/vue-i18n/releases/tag/v9.14.0)

[Compare Source](https://redirect.github.com/intlify/vue-i18n/compare/v9.13.1...v9.14.0)

<!-- Release notes generated using configuration in .github/release.yml at v9.14.0 -->

#### What's Changed

##### ⚡ Improvement Features

-   fix: vue-i18n type definition for vue package by [@&#8203;BobbieGoede](https://redirect.github.com/BobbieGoede) in [https://github.com/intlify/vue-i18n/pull/1919](https://redirect.github.com/intlify/vue-i18n/pull/1919)

**Full Changelog**: https://github.com/intlify/vue-i18n/compare/v9.13.1...v9.14.0

### [`v9.13.1`](https://redirect.github.com/intlify/vue-i18n/blob/HEAD/CHANGELOG.md#v9131-2024-04-20T152552Z)

[Compare Source](https://redirect.github.com/intlify/vue-i18n/compare/v9.13.0...v9.13.1)

This changelog is generated by [GitHub Releases](https://redirect.github.com/intlify/vue-i18n-next/releases/tag/v9.13.1)

<!-- Release notes generated using configuration in .github/release.yml at v9.13.1 -->

#### What's Changed

##### 🐛 Bug Fixes

-   fix(message-compiler): cannot resolve none-identifier characters at linked key by [@&#8203;kazupon](https://redirect.github.com/kazupon) in [https://github.com/intlify/vue-i18n-next/pull/1813](https://redirect.github.com/intlify/vue-i18n-next/pull/1813)

**Full Changelog**: https://github.com/intlify/vue-i18n-next/compare/v9.13.0...v9.13.1

### [`v9.13.0`](https://redirect.github.com/intlify/vue-i18n/blob/HEAD/CHANGELOG.md#v9130-2024-04-17T144738Z)

[Compare Source](https://redirect.github.com/intlify/vue-i18n/compare/v9.12.1...v9.13.0)

This changelog is generated by [GitHub Releases](https://redirect.github.com/intlify/vue-i18n-next/releases/tag/v9.13.0)

<!-- Release notes generated using configuration in .github/release.yml at v9.13.0 -->

#### What's Changed

##### ⚠️ Deprecated Features

-   fix: EOL announcement warning for vue-i18n-bridge by [@&#8203;kazupon](https://redirect.github.com/kazupon) in [https://github.com/intlify/vue-i18n-next/pull/1800](https://redirect.github.com/intlify/vue-i18n-next/pull/1800)

##### ⚡ Improvement Features

-   fix: not throw warnings when using implicit fallback by [@&#8203;ShinnosukeKomiya](https://redirect.github.com/ShinnosukeKomiya) in [https://github.com/intlify/vue-i18n-next/pull/1798](https://redirect.github.com/intlify/vue-i18n-next/pull/1798)

##### 📝️ Documentations

-   fix: spelling by [@&#8203;DamageESP](https://redirect.github.com/DamageESP) in [https://github.com/intlify/vue-i18n-next/pull/1802](https://redirect.github.com/intlify/vue-i18n-next/pull/1802)
-   docs: improve documentation by [@&#8203;kazupon](https://redirect.github.com/kazupon) in [https://github.com/intlify/vue-i18n-next/pull/1801](https://redirect.github.com/intlify/vue-i18n-next/pull/1801)
-   docs: fix dead link on menu by [@&#8203;kazupon](https://redirect.github.com/kazupon) in [https://github.com/intlify/vue-i18n-next/pull/1804](https://redirect.github.com/intlify/vue-i18n-next/pull/1804)

#### New Contributors

-   [@&#8203;ShinnosukeKomiya](https://redirect.github.com/ShinnosukeKomiya) made their first contribution in [https://github.com/intlify/vue-i18n-next/pull/1798](https://redirect.github.com/intlify/vue-i18n-next/pull/1798)
-   [@&#8203;DamageESP](https://redirect.github.com/DamageESP) made their first contribution in [https://github.com/intlify/vue-i18n-next/pull/1802](https://redirect.github.com/intlify/vue-i18n-next/pull/1802)

**Full Changelog**: https://github.com/intlify/vue-i18n-next/compare/v9.12.1...v9.13.0

### [`v9.12.1`](https://redirect.github.com/intlify/vue-i18n/blob/HEAD/CHANGELOG.md#v9121-2024-04-14T104811Z)

[Compare Source](https://redirect.github.com/intlify/vue-i18n/compare/v9.12.0...v9.12.1)

This changelog is generated by [GitHub Releases](https://redirect.github.com/intlify/vue-i18n-next/releases/tag/v9.12.1)

<!-- Release notes generated using configuration in .github/release.yml at v9.12.1 -->

#### What's Changed

##### 🐛 Bug Fixes

-   fix: compile error for key with included hyphen in named interpolation by [@&#8203;kazupon](https://redirect.github.com/kazupon) in [https://github.com/intlify/vue-i18n-next/pull/1797](https://redirect.github.com/intlify/vue-i18n-next/pull/1797)

##### 👕 Refactoring

-   refactor: tokenizer by [@&#8203;kazupon](https://redirect.github.com/kazupon) in [https://github.com/intlify/vue-i18n-next/pull/1799](https://redirect.github.com/intlify/vue-i18n-next/pull/1799)

**Full Changelog**: https://github.com/intlify/vue-i18n-next/compare/v9.12.0...v9.12.1

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/intlify/eslint-plugin-vue-i18n).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzkuNDIuNCIsInRhcmdldEJyYW5jaCI6Im1hc3RlciIsImxhYmVscyI6WyJUeXBlOiBEZXBlbmRlbmN5Il19-->


cloudflare-workers-and-pages[bot]: ## Deploying eslint-plugin-vue-i18n 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>d5dbbaf</code>
</td></tr>
<tr><td><strong>Status:</strong></td><td>⚡️&nbsp; Build in progress...</td></tr>
</table>

[View logs](https://dash.cloudflare.com/?to=/:account/pages/view/eslint-plugin-vue-i18n/cca56bba-a007-41e6-bef3-b44d0d29b6a2)

changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: d5dbbaf5622168ad66791dbb78ac365ae1b7d46b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/intlify/eslint-plugin-vue-i18n/new/renovate/intlify-message-compiler-10.x?filename=.changeset/honest-cups-sit.md&value=---%0A%22%40intlify%2Feslint-plugin-vue-i18n%22%3A%20patch%0A---%0A%0Afix(deps)%3A%20update%20dependency%20%40intlify%2Fmessage-compiler%20to%20v10%0A)



Patch:
diff --git a/.changeset/new-ligers-tan.md b/.changeset/new-ligers-tan.md
new file mode 100644
index 0000000..393c531
--- /dev/null
+++ b/.changeset/new-ligers-tan.md
@@ -0,0 +1,5 @@
+---
+"@intlify/eslint-plugin-vue-i18n": major
+---
+
+fix(deps): update dependency @intlify/message-compiler to v10
diff --git a/lib/rules/no-deprecated-modulo-syntax.ts b/lib/rules/no-deprecated-modulo-syntax.ts
index 59e237f..3e5e56c 100644
--- a/lib/rules/no-deprecated-modulo-syntax.ts
+++ b/lib/rules/no-deprecated-modulo-syntax.ts
@@ -13,7 +13,7 @@ import {
   getMessageSyntaxVersions,
   NodeTypes
 } from '../utils/message-compiler/utils'
-import { parse } from '../utils/message-compiler/parser'
+import { parse } from '../utils/message-compiler/parser-v9'
 import { traverseNode } from '../utils/message-compiler/traverser'
 import {
   createRule,
@@ -75,8 +75,6 @@ function create(context: RuleContext): RuleListener {
     }
     if (messageSyntaxVersions.v9) {
       verifyForV9(message, reportNode, getReportOffset)
-    } else if (messageSyntaxVersions.v8) {
-      return
     }
   }
 
diff --git a/lib/rules/prefer-linked-key-with-paren.ts b/lib/rules/prefer-linked-key-with-paren.ts
index b22685f..4ca8d7f 100644
--- a/lib/rules/prefer-linked-key-with-paren.ts
+++ b/lib/rules/prefer-linked-key-with-paren.ts
@@ -42,7 +42,7 @@ function create(context: RuleContext): RuleListener {
   const sourceCode = getSourceCode(context)
   const messageSyntaxVersions = getMessageSyntaxVersions(context)
 
-  function verifyForV9(
+  function verifyForNewSyntax(
     message: string,
     reportNode: JSONAST.JSONStringLiteral | YAMLAST.YAMLScalar,
     getReportOffset: GetReportOffset
@@ -134,14 +134,16 @@ function create(context: RuleContext): RuleListener {
     if (messageSyntaxVersions.reportIfMissingSetting()) {
       return
     }
-    if (messageSyntaxVersions.v9 && messageSyntaxVersions.v8) {
+    const newSyntax = messageSyntaxVersions.v9 || messageSyntaxVersions.v10
+    const v8Syntax = messageSyntaxVersions.v8
+    if (newSyntax && v8Syntax) {
       // This rule cannot support two versions in the same project.
       return
     }
 
-    if (messageSyntaxVersions.v9) {
-      verifyForV9(message, reportNode, getReportOffset)
-    } else if (messageSyntaxVersions.v8) {
+    if (newSyntax) {
+      verifyForNewSyntax(message, reportNode, getReportOffset)
+    } else if (v8Syntax) {
       verifyForV8(message, reportNode, getReportOffset)
     }
   }
diff --git a/lib/rules/valid-message-syntax.ts b/lib/rules/valid-message-syntax.ts
index f64a5ef..e7b5f4a 100644
--- a/lib/rules/valid-message-syntax.ts
+++ b/lib/rules/valid-message-syntax.ts
@@ -14,6 +14,7 @@ import {
   getReportIndex
 } from '../utils/message-compiler/utils'
 import { parse } from '../utils/message-compiler/parser'
+import { parse as parseForV9 } from '../utils/message-compiler/parser-v9'
 import { parse as parseForV8 } from '../utils/message-compiler/parser-v8'
 import type { CompileError } from '@intlify/message-compiler'
 import { createRule } from '../utils/rule'
@@ -27,9 +28,16 @@ function create(context: RuleContext): RuleListener {
   const messageSyntaxVersions = getMessageSyntaxVersions(context)
 
   function* extractMessageErrors(message: string) {
-    if (messageSyntaxVersions.v9) {
-      yield* parse(message).errors
+    // v10 and v9 generate nearly identical errors so only one of them will be returned.
+    const errorsForV10OrV9: CompileError[] = []
+    if (messageSyntaxVersions.v10) {
+      errorsForV10OrV9.push(...parse(message).errors)
     }
+    if (messageSyntaxVersions.v9 && !errorsForV10OrV9.length) {
+      errorsForV10OrV9.push(...parseForV9(message).errors)
+    }
+    yield* errorsForV10OrV9
+
     if (messageSyntaxVersions.v8) {
       yield* parseForV8(message).errors
     }
diff --git a/lib/utils/collect-linked-keys.ts b/lib/utils/collect-linked-keys.ts
index 9221dee..82fb75a 100644
--- a/lib/utils/collect-linked-keys.ts
+++ b/lib/utils/collect-linked-keys.ts
@@ -6,6 +6,7 @@ import type { ResourceNode } from '@intlify/message-compiler'
 import { traverseNode } from './message-compiler/traverser'
 import type { I18nLocaleMessageDictionary, RuleContext } from '../types'
 import { parse } from './message-compiler/parser'
+import { parse as parseForV9 } from './message-compiler/parser-v9'
 import { parse as parseForV8 } from './message-compiler/parser-v8'
 import type { MessageSyntaxVersions } from './message-compiler/utils'
 import { NodeTypes } from './message-compiler/utils'
@@ -27,9 +28,12 @@ function* extractUsedKeysFromLinks(
     if (typeof value === 'object') {
       yield* extractUsedKeysFromLinks(value, messageSyntaxVersions)
     } else if (typeof value === 'string') {
-      if (messageSyntaxVersions.v9) {
+      if (messageSyntaxVersions.v10) {
         yield* extractUsedKeysFromAST(parse(value).ast)
       }
+      if (messageSyntaxVersions.v9) {
+        yield* extractUsedKeysFromAST(parseForV9(value).ast)
+      }
       if (messageSyntaxVersions.v8) {
         yield* extractUsedKeysFromAST(parseForV8(value).ast)
       }
diff --git a/lib/utils/message-compiler/parser-v8.ts b/lib/utils/message-compiler/parser-v8.ts
index 100cc62..bce8627 100644
--- a/lib/utils/message-compiler/parser-v8.ts
+++ b/lib/utils/message-compiler/parser-v8.ts
@@ -17,6 +17,7 @@ import type {
 } from '@intlify/message-compiler'
 import { sortedLastIndex } from 'lodash'
 import { NodeTypes } from './utils'
+import type { ModuloNamedNode } from './parser-v9'
 
 export function parse(code: string): {
   ast: ResourceNode
@@ -207,7 +208,7 @@ function parseAST(code: string, errors: CompileError[]): ResourceNode {
           node = listNode
         }
         if (!node) {
-          const namedNode: NamedNode = {
+          const namedNode: ModuloNamedNode = {
             type: NodeTypes.Named,
             key: trimmedKeyValue,
             ...ctx.getNodeLoc(endOffset - 1, placeholderEndOffset)
diff --git a/lib/utils/message-compiler/parser-v9.ts b/lib/utils/message-compiler/parser-v9.ts
new file mode 100644
index 0000000..68f1ea6
--- /dev/null
+++ b/lib/utils/message-compiler/parser-v9.ts
@@ -0,0 +1,59 @@
+/**
+ * A simplified version of the message parser that handles messages like vue-i18n v8.
+ * This parser probably has poor performance.
+ */
+import type {
+  CompileError,
+  NamedNode,
+  ResourceNode
+} from '@intlify/message-compiler'
+import { NodeTypes } from './utils'
+import { parse as baseParse } from './parser'
+import type { MessageElementNode } from './traverser'
+import { traverseNode } from './traverser'
+
+// The deprecated Rails i18n format.
+export type ModuloNamedNode = NamedNode & { modulo?: boolean }
+
+export function parse(code: string): {
+  ast: ResourceNode
+  errors: CompileError[]
+} {
+  const { ast, errors } = baseParse(code)
+
+  traverseNode(ast, node => {
+    if (node.type === NodeTypes.Message) {
+      transformModuloNamedNode(node.items)
+    }
+  })
+  return {
+    ast,
+    errors
+  }
+
+  function transformModuloNamedNode(nodes: MessageElementNode[]) {
+    // Converts nodes with a '%' before the brackets into modulo nodes.
+    for (let index = nodes.length - 1; index >= 1; index--) {
+      const node = nodes[index]
+      if (
+        node.type !== NodeTypes.Named ||
+        code[node.loc!.start.offset - 1] !== '%'
+      )
+        continue
+
+      const prev = nodes[index - 1]
+      if (prev.type !== NodeTypes.Text || !prev.value?.endsWith('%')) continue
+
+      node.modulo = true
+
+      prev.loc!.end.offset -= 1
+      prev.loc!.end.column -= 1
+      prev.end! -= 1
+      prev.value = prev.value!.slice(0, -1)
+      if (prev.start === prev.end) {
+        nodes.splice(index - 1, 1)
+        index--
+      }
+    }
+  }
+}
diff --git a/lib/utils/message-compiler/traverser.ts b/lib/utils/message-compiler/traverser.ts
index 84ee1ab..360d558 100644
--- a/lib/utils/message-compiler/traverser.ts
+++ b/lib/utils/message-compiler/traverser.ts
@@ -11,13 +11,15 @@ import type {
   TextNode
 } from '@intlify/message-compiler'
 import { NodeTypes } from './utils'
+import type { ModuloNamedNode } from './parser-v9'
 
-type MessageElementNode =
+export type MessageElementNode =
   | TextNode
   | NamedNode
   | ListNode
   | LiteralNode
   | LinkedNode
+  | ModuloNamedNode
 type MessageASTNode =
   | ResourceNode
   | PluralNode
diff --git a/lib/utils/message-compiler/utils.ts b/lib/utils/message-compiler/utils.ts
index e2bdfa1..24a7e56 100644
--- a/lib/utils/message-compiler/utils.ts
+++ b/lib/utils/message-compiler/utils.ts
@@ -19,6 +19,7 @@ export const NodeTypes = {
 export type MessageSyntaxVersions = {
   v8: boolean
   v9: boolean
+  v10: boolean
   isNotSet: boolean
   reportIfMissingSetting: () => boolean
 }
@@ -37,6 +38,7 @@ export function getMessageSyntaxVersions(
     return {
       v8: true,
       v9: true,
+      v10: true,
       isNotSet: true,
       reportIfMissingSetting: () => {
         if (!puttedSettingsError.has(context)) {
@@ -54,7 +56,8 @@ export function getMessageSyntaxVersions(
   const range = new Range(messageSyntaxVersion)
   return {
     v8: intersects(range, '^8.0.0 || <=8.0.0'),
-    v9: intersects(range, '>=9.0.0-0'),
+    v9: intersects(range, '^9.0.0-0'),
+    v10: intersects(range, '>=10.0.0-0'),
     isNotSet: false,
     reportIfMissingSetting: () => false
   }
diff --git a/package.json b/package.json
index 6851f0d..9ea3af5 100644
--- a/package.json
+++ b/package.json
@@ -29,7 +29,7 @@
   "engines": {
     "node": ">=18.0.0"
   },
-  "packageManager": "pnpm@9.14.4",
+  "packageManager": "pnpm@9.15.0",
   "type": "commonjs",
   "files": [
     "dist"
@@ -61,7 +61,7 @@
   "dependencies": {
     "@eslint/eslintrc": "^3.0.0",
     "@intlify/core-base": "^10.0.0",
-    "@intlify/message-compiler": "^9.12.0",
+    "@intlify/message-compiler": "^10.0.5",
     "debug": "^4.3.4",
     "eslint-compat-utils": "^0.6.0",
     "glob": "^10.3.3",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4a3d35e..d751c78 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -15,8 +15,8 @@ importers:
         specifier: ^10.0.0
         version: 10.0.5
       '@intlify/message-compiler':
-        specifier: ^9.12.0
-        version: 9.12.0
+        specifier: ^10.0.5
+        version: 10.0.5
       debug:
         specifier: ^4.3.4
         version: 4.3.4
@@ -654,18 +654,10 @@ packages:
     resolution: {integrity: sha512-6GT1BJ852gZ0gItNZN2krX5QAmea+cmdjMvsWohArAZ3GmHdnNANEcF9JjPXAMRtQ6Ux5E269ymamg/+WU6tQA==}
     engines: {node: '>= 16'}
 
-  '@intlify/message-compiler@9.12.0':
-    resolution: {integrity: sha512-2c6VwhvVJ1nur+2cN2NjdrmrV6vXjvyxYVvtUYMXKsWSUwoNURHGds0xJVJmWxbF8qV9oGepcVV6xl9bvadEIg==}
-    engines: {node: '>= 16'}
-
   '@intlify/shared@10.0.5':
     resolution: {integrity: sha512-bmsP4L2HqBF6i6uaMqJMcFBONVjKt+siGluRq4Ca4C0q7W2eMaVZr8iCgF9dKbcVXutftkC7D6z2SaSMmLiDyA==}
     engines: {node: '>= 16'}
 
-  '@intlify/shared@9.12.0':
-    resolution: {integrity: sha512-uBcH55x5CfZynnerWHQxrXbT6yD6j6T7Nt+R2+dHAOAneoMd6BoGvfEzfYscE94rgmjoDqdr+PdGDBLk5I5EjA==}
-    engines: {node: '>= 16'}
-
   '@isaacs/cliui@8.0.2':
     resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
     engines: {node: '>=12'}
@@ -2791,10 +2783,6 @@ packages:
     engines: {node: '>=6'}
     hasBin: true
 
-  source-map-js@1.2.0:
-    resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
-    engines: {node: '>=0.10.0'}
-
   source-map-js@1.2.1:
     resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
     engines: {node: '>=0.10.0'}
@@ -3857,15 +3845,8 @@ snapshots:
       '@intlify/shared': 10.0.5
       source-map-js: 1.2.1
 
-  '@intlify/message-compiler@9.12.0':
-    dependencies:
-      '@intlify/shared': 9.12.0
-      source-map-js: 1.2.0
-
   '@intlify/shared@10.0.5': {}
 
-  '@intlify/shared@9.12.0': {}
-
   '@isaacs/cliui@8.0.2':
     dependencies:
       string-width: 5.1.2
@@ -6112,8 +6093,6 @@ snapshots:
       wcwidth: 1.0.1
       yargs: 15.4.1
 
-  source-map-js@1.2.0: {}
-
   source-map-js@1.2.1: {}
 
   source-map@0.6.1: {}


Test patch:
diff --git a/tests/lib/rules/no-deprecated-modulo-syntax.ts b/tests/lib/rules/no-deprecated-modulo-syntax.ts
index 448d0b9..bc4fae5 100644
--- a/tests/lib/rules/no-deprecated-modulo-syntax.ts
+++ b/tests/lib/rules/no-deprecated-modulo-syntax.ts
@@ -18,7 +18,7 @@ const tester = new RuleTester({
   languageOptions: { parser: vueParser, ecmaVersion: 2015 }
 })
 
-tester.run('no-deprecated-module-syntax', rule as never, {
+tester.run('no-deprecated-modulo-syntax', rule as never, {
   valid: [
     // text only
     {
diff --git a/tests/lib/rules/valid-message-syntax.ts b/tests/lib/rules/valid-message-syntax.ts
index 40c7da5..4b1195f 100644
--- a/tests/lib/rules/valid-message-syntax.ts
+++ b/tests/lib/rules/valid-message-syntax.ts
@@ -223,24 +223,25 @@ tester.run('valid-message-syntax', rule as never, {
         }
       ]
     },
-    {
-      code: `
-      key: message @:(v8)
-      `,
-      ...options.yaml.default,
-      errors: [
-        {
-          message: `If you want to use '${TEST_RULE_ID_PREFIX}valid-message-syntax' rule, you need to set 'messageSyntaxVersion' at 'settings'. See the 'eslint-plugin-vue-i18n' documentation`,
-          line: 1,
-          column: 1
-        },
-        {
-          message: 'Unexpected empty linked key',
-          line: 2,
-          column: 21
-        }
-      ]
-    },
+    // {
+    //   // The syntax is now allowed.
+    //   code: `
+    //   key: message @:(v8)
+    //   `,
+    //   ...options.yaml.default,
+    //   errors: [
+    //     {
+    //       message: `If you want to use '${TEST_RULE_ID_PREFIX}valid-message-syntax' rule, you need to set 'messageSyntaxVersion' at 'settings'. See the 'eslint-plugin-vue-i18n' documentation`,
+    //       line: 1,
+    //       column: 1
+    //     },
+    //     {
+    //       message: 'Unexpected empty linked key',
+    //       line: 2,
+    //       column: 21
+    //     }
+    //   ]
+    // },
     {
       code: `
       key: message { v9 }
@@ -272,61 +273,65 @@ tester.run('valid-message-syntax', rule as never, {
         }
       ]
     },
-    {
-      code: `
-      key: message @:(v8)
-      `,
-      ...options.yaml.v9,
-      errors: [
-        {
-          message: 'Unexpected empty linked key',
-          line: 2,
-          column: 21
-        }
-      ]
-    },
-    {
-      code: `
-      key: message new line
-        @:(v8)
-      `,
-      ...options.yaml.v9,
-      errors: [
-        {
-          message: 'Unexpected empty linked key',
-          line: 3,
-          column: 10
-        }
-      ]
-    },
-    {
-      code: `
-      key: "message new line
-        @:(v8)"
-      `,
-      ...options.yaml.v9,
-      errors: [
-        {
-          message: 'Unexpected empty linked key',
-          line: 3,
-          column: 10
-        }
-      ]
-    },
-    {
-      code: `
-      key: 'message new line
-        @:(v8)'
-      `,
-      ...options.yaml.v9,
-      errors: [
-        {
-          message: 'Unexpected empty linked key',
-          line: 3,
-          column: 10
-        }
-      ]
-    },
+    // {
+    //   // The syntax is now allowed.
+    //   code: `
+    //   key: message @:(v8)
+    //   `,
+    //   ...options.yaml.v9,
+    //   errors: [
+    //     {
+    //       message: 'Unexpected empty linked key',
+    //       line: 2,
+    //       column: 21
+    //     }
+    //   ]
+    // },
+    // {
+    //   // The syntax is now allowed.
+    //   code: `
+    //   key: message new line
+    //     @:(v8)
+    //   `,
+    //   ...options.yaml.v9,
+    //   errors: [
+    //     {
+    //       message: 'Unexpected empty linked key',
+    //       line: 3,
+    //       column: 10
+    //     }
+    //   ]
+    // },
+    // {
+    //   // The syntax is now allowed.
+    //   code: `
+    //   key: "message new line
+    //     @:(v8)"
+    //   `,
+    //   ...options.yaml.v9,
+    //   errors: [
+    //     {
+    //       message: 'Unexpected empty linked key',
+    //       line: 3,
+    //       column: 10
+    //     }
+    //   ]
+    // },
+    // {
+    //   // The syntax is now allowed.
+    //   code: `
+    //   key: 'message new line
+    //     @:(v8)'
+    //   `,
+    //   ...options.yaml.v9,
+    //   errors: [
+    //     {
+    //       message: 'Unexpected empty linked key',
+    //       line: 3,
+    //       column: 10
+    //     }
+    //   ]
+    // },
     {
       code: `
       <i18n lang="yaml">
@@ -476,16 +481,6 @@ tester.run('valid-message-syntax', rule as never, {
           line: 3,
           column: 22
         },
-        {
-          message: 'Unterminated closing brace',
-          line: 4,
-          column: 27
-        },
-        {
-          message: 'Unbalanced closing brace',
-          line: 4,
-          column: 34
-        },
         {
           message: "Unexpected 'null' message",
           line: 5,
diff --git a/tests/lib/utils/message-compiler/parser-v8.ts b/tests/lib/utils/message-compiler/parser-v8.ts
index f117022..5505029 100644
--- a/tests/lib/utils/message-compiler/parser-v8.ts
+++ b/tests/lib/utils/message-compiler/parser-v8.ts
@@ -3,7 +3,7 @@
  */
 import { deepStrictEqual } from 'assert'
 import { parse } from '../../../../lib/utils/message-compiler/parser-v8'
-import { parse as parseForV9 } from '../../../../lib/utils/message-compiler/parser'
+import { parse as parseForV9 } from '../../../../lib/utils/message-compiler/parser-v9'
 import { errorsFixtures } from './parser-v8-data'
 
 describe('parser-v8', () => {
diff --git a/tests/lib/utils/message-compiler/utils.ts b/tests/lib/utils/message-compiler/utils.ts
index 44cefc0..071a449 100644
--- a/tests/lib/utils/message-compiler/utils.ts
+++ b/tests/lib/utils/message-compiler/utils.ts
@@ -21,31 +21,37 @@ describe('message-compiler utils', () => {
       deepStrictEqual(get('^8.0.0'), {
         v8: true,
         v9: false,
+        v10: false,
         isNotSet: false
       })
       deepStrictEqual(get('^9.0.0'), {
         v8: false,
         v9: true,
+        v10: false,
         isNotSet: false
       })
       deepStrictEqual(get('^7.0.0'), {
         v8: true,
         v9: false,
+        v10: false,
         isNotSet: false
       })
       deepStrictEqual(get('^10.0.0'), {
         v8: false,
-        v9: true,
+        v9: false,
+        v10: true,
         isNotSet: false
       })
       deepStrictEqual(get('>=5.0.0'), {
         v8: true,
         v9: true,
+        v10: true,
         isNotSet: false
       })
       deepStrictEqual(get('^9.0.0-beta.8'), {
         v8: false,
         v9: true,
+        v10: false,
         isNotSet: false
       })
     })