💌

vue-i18n で特殊文字に関するエラーに遭遇したあなたへ

2024/03/08に公開

はじめに

Nuxt3 で Nuxt I18n を利用しているときに以下のエラーに遭遇しました。

Internal server error: Invalid linked format (error code: 10)

原因を調査するとメールアドレスで利用していた@が原因と分かりました。
本記事では原因と解決方法を調査してまとめました。

環境

nuxt.config.tsの i18n 設定は以下のとおりです。

nuxt.config.ts
export default defineNuxtConfig({
  // ...other options
  modules: [
    "@nuxtjs/i18n",
    // ...other modules
  ],
  i18n: {
    langDir: "locales/",
    defaultLocale: "ja",
    locales: [
      {
        code: "ja",
        iso: "ja-JP",
        file: "ja.json",
        name: "日本語",
      },
    ],
  },
});

特殊文字とは

Vue I18n のドキュメントを見てみる特殊文字についての説明がありました。

The following characters used in the message format syntax are processed by the compiler as special characters:

  • {
  • }
  • @
  • $
  • |

ドキュメントを読むと{}@$|が特殊文字として処理されるようです。

https://vue-i18n.intlify.dev/guide/essentials/syntax#special-characters

vue-i18n で特殊文字を利用したい場合は?

では、vue-i18n で特殊文字を利用したい場合はどうすれば良いのでしょうか。特殊文字のページにて以下のような案内が明記されています。

If you want to use these characters, you will need to use the Literal interpolation.

リテラル文字列を用いたリテラル補間が可能のようです。このように明記されててありがたい限りです。ガイドに従い リテラル補間 のセクションを確認します。

https://vue-i18n.intlify.dev/guide/essentials/syntax#literal-interpolation

以下のように修正してみました

リテラル補間を用いて以下のように修正してみました。

ja.json
{
  "email": {
    "title": "メールアドレスです",
-   "hint": "xyz@example.com",
+   "hint": "xyz{'@'}example.com",
    "description": ""
  }
}

可変値で利用する場合は?

上記ではxyz@example.comという固定値でしたがuser1@example.comuser2@example.comのような可変値を利用したい場合はどうでしょうか。この場合は通常の vue-i18n の value 利用 + リテラル補間で問題ありません。

例を示します。以下のようなケースを考えてみます。

ja.json
{
  "address": "{account}{'@'}example.com",
  "address2": "{account}{'@'}{domain}",
}

この場合はテンプレート側から以下のように呼び出します。

<template>
  <div>
    <p>Address: {{ $t("address", { account: "user1" }) }}</p>
    <p>
      Sub Address:
      {{ $t("address2", { account: "user1", domain: "example2.com" }) }}
    </p>
  </div>
</template>


Nuxt の例は以下の通りです。

※ 以下の例ではuseI18n()を利用していますが$t()でも問題なく動作します。詳しくはNuxt I18n のドキュメントを参照ください。

<script setup lang="ts">
// useI18nはAuto importsされている
const { t } = useI18n();
</script>
<template>
  <div>
    <p>Address: {{ t("address", { account: "user1" }) }}</p>
    <p>
      Sub Address:
      {{ t("address2", { account: "user1", domain: "example2.com" }) }}
    </p>
  </div>
</template>

おわりに

今回は vue-i18n の特殊文字について調査を行いました。
vue-i18n は歴史が長いため同問題に遭遇している人は多いのかなと予想しています。
ただ、小ネタということもあり記事化されていない印象です。

同様の問題で困っている方の手助けになれば幸いです!

Vue・Nuxt 情報が集まる広場 / Plaza for Vue・Nuxt.

Discussion