🐉

Vuetify3のVDatePickerの日本語化

はじめに

皆さんVuetifyは利用されているでしょうか?
Vuetify2を利用して作成されてきたプロジェクトの多くはVuetify3への移行を検討されているかと思います。しかしながら、Vuetify2からVuetify3で破壊的な変更も多く、簡単には移行できないコンポーネントも存在しますし、2024年1月時点では、まだまだ情報も少ない状況です。
そこで、今回はVuetify2からVuetify3で大きく仕様変更がされたVDatePickerの日本語化の方法を、試行錯誤した部分も含めて紹介したいと思います。
v3.4.0v3.5.1のVuetify3での内容になります。v3.5.2以降を使用している場合は別解2を参考としてください。

VDatePickerの実装

まずはデフォルトのVDatePickerを実装してみます。
Vuetify3の導入まで完了している必要はありますが、導入が完了していれば、公式のドキュメントでも紹介されているとおり、以下のようにv-date-pickerタグを差し込むだけです。

App.vue
<template>
  <v-app>
    <v-date-picker></v-date-picker>
  </v-app>
</template>

う~ん、簡単!
でも待ってほしい。英語です…
VDatePicker英語
ここから私のVDatePicker日本語化への道が始まりました。

VLocaleProviderを使ってみる

Vuetify2の頃はPropsにlocaleがあったため、以下のように書けば日本語化できました。

App.vue
<template>
  <v-app>
    <v-date-picker locale="jp-ja"></v-date-picker>
  </v-app>
</template>

Vuetify3ではVDatePickerにPropsにlocaleがないため、VLocaleProviderを使ってみます。

App.vue
<template>
  <v-app>
    <v-locale-provider locale="ja">
      <v-date-picker></v-date-picker>
    </v-locale-provider>
  </v-app>
</template>

う~ん、簡単!
でも待ってほしい。カレンダーに〇日っておかしくないか…
VDatePicker日本語
これはVuetify2のVDatePickerでもあった事象でVuetify2のときはPropsにday-formatがあったので、以下のように書けば対処可能でした。

App.vue
<template>
  <v-app>
    <v-date-picker
      locale="jp-ja"
      :day-format="(date) => new Date(date).getDate()"
    ></v-date-picker>
  </v-app>
</template>

Vuetify3のVDatePickerのPropsにday-formatは………ないやん…

DateFnsAdapterを使ってみる

落ち着いて、あらためて公式のVDatePickerのドキュメントを読み返します。
Internationalization(国際化)の記述があり、@date-io/date-fns(DateFnsAdapter)を使う方法が紹介されています。
これでいけるのでは…早速利用してみましょう。
まずは@date-io/date-fnsとdate-fnsを導入します。

npm i @date-io/date-fns
npm i date-fns

そして、main.tsにDateFnsAdapterを追加
※公式のVDatePickerのドキュメントどおりだとブラウザのコンソールにエラーが出るので少し変えてます。

main.ts
import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'

// Vuetify
import '@mdi/font/css/materialdesignicons.css'
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
import DateFnsAdapter from '@date-io/date-fns'
import { ja } from 'date-fns/locale'

const vuetify = createVuetify({
  date: {
    adapter: new DateFnsAdapter({
        locale: ja,
    }),
  },
  components,
  directives,
})

createApp(App).use(vuetify).mount('#app')
App.vue
<template>
  <v-app>
    <v-date-picker></v-date-picker>
  </v-app>
</template>

日が消えた!でも何か色々おかしい!!
VDatePicker日本語修正
もうドキュメントには頼らない!ソースみる!!

ソースをみて各フォーマットを変更

落ち着いて、VuetifyのVDatePickerのソースをみます。

VDatePicker.tsx
    const header = computed(() => {
      return props.multiple && model.value.length > 1
        ? t('$vuetify.datePicker.itemsSelected', model.value.length)
        : model.value[0] && adapter.isValid(model.value[0])
          ? adapter.format(model.value[0], 'normalDateWithWeekday')
          : t(props.header)
    })
    const text = computed(() => {
      return adapter.format(
        adapter.setYear(adapter.setMonth(adapter.date(), month.value), year.value),
        'monthAndYear',
      )
    })

あっ、adapter.format…(ここで、DateFnsAdapterでフォーマットが指定できることに気づく)
以下のように書き換えます。

main.ts
import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'

// Vuetify
import '@mdi/font/css/materialdesignicons.css'
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
import DateFnsAdapter from '@date-io/date-fns'
import { ja } from 'date-fns/locale'

const vuetify = createVuetify({
  date: {
    adapter: new DateFnsAdapter({
        formats: {
          year: 'yyyy年',
          monthAndYear: 'yyyy年M月',
          normalDateWithWeekday: 'M月d日(E)',
        },
        locale: ja,
    }),
  },
  components,
  directives,
})

createApp(App).use(vuetify).mount('#app')
App.vue
<template>
  <v-app>
    <v-date-picker></v-date-picker>
  </v-app>
</template>

できた!
VDatePicker日本語完成

別解1(2024/1/30追記)

DateFnsAdapterを使う以外の方法がGitHubのプルリクエストにあったので、追記。
こっちの方が公式という感じかも…ちゃんと見ていなくて反省…
以下のように、VLocaleProviderを使いつつ、createVuetify関数で日のフォーマットを変えます。

main.ts
import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'

// Vuetify
import '@mdi/font/css/materialdesignicons.css'
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'

const vuetify = createVuetify({
  date: {
    formats: {
      dayOfMonth: (date: Date) => date.getDate(),
    },
  },
  components,
  directives,
})

createApp(App).use(vuetify).mount('#app')
App.vue
<template>
  <v-app>
    <v-locale-provider locale="ja">
      <v-date-picker></v-date-picker>
    </v-locale-provider>
  </v-app>
</template>

これでも上で紹介した完成形と同じ状態になります。
毎回、v-locale-providerタグを書きたくないとかなければ、こちらの方がよいかもしれません。

別解2(2024/2/1追記)

v3.5.2でVLocaleProviderで日本語化したときに〇日となる問題が修正されました🎉
(仕様だと思ってた…)
「date: format dayOfMonth with NumberFormat instead of DateTimeFormat (d0136e0), closes #18093」
なので、v3.5.2以降のバージョンに更新すれば、VLocaleProviderを使うだけで日本語化できます。

App.vue
<template>
  <v-app>
    <v-locale-provider locale="ja">
      <v-date-picker></v-date-picker>
    </v-locale-provider>
  </v-app>
</template>

う~ん、簡単!(あれ…この記事意味あったか?)

まとめ

以上がVuetify3のVDatePickerの日本語化の方法になります。
最終的なソースコードは以下に上げていますので、参考としてください。
https://github.com/y-kashima-iandc/vuetify-date-picker-ja

参考文献

この記事は以下の情報を参考にして執筆しました。

株式会社アイアンドシー Tech Blog

Discussion