Vuetify3のVDatePickerの日本語化
はじめに
皆さんVuetifyは利用されているでしょうか?
Vuetify2を利用して作成されてきたプロジェクトの多くはVuetify3への移行を検討されているかと思います。しかしながら、Vuetify2からVuetify3で破壊的な変更も多く、簡単には移行できないコンポーネントも存在しますし、2024年1月時点では、まだまだ情報も少ない状況です。
そこで、今回はVuetify2からVuetify3で大きく仕様変更がされたVDatePickerの日本語化の方法を、試行錯誤した部分も含めて紹介したいと思います。
※v3.4.0~v3.5.1のVuetify3での内容になります。v3.5.2以降を使用している場合は別解2を参考としてください。
VDatePickerの実装
まずはデフォルトのVDatePickerを実装してみます。
Vuetify3の導入まで完了している必要はありますが、導入が完了していれば、公式のドキュメントでも紹介されているとおり、以下のようにv-date-pickerタグを差し込むだけです。
<template>
<v-app>
<v-date-picker></v-date-picker>
</v-app>
</template>
う~ん、簡単!
でも待ってほしい。英語です…
ここから私のVDatePicker日本語化への道が始まりました。
VLocaleProviderを使ってみる
Vuetify2の頃はPropsにlocaleがあったため、以下のように書けば日本語化できました。
<template>
<v-app>
<v-date-picker locale="jp-ja"></v-date-picker>
</v-app>
</template>
Vuetify3ではVDatePickerにPropsにlocaleがないため、VLocaleProviderを使ってみます。
<template>
<v-app>
<v-locale-provider locale="ja">
<v-date-picker></v-date-picker>
</v-locale-provider>
</v-app>
</template>
う~ん、簡単!
でも待ってほしい。カレンダーに〇日っておかしくないか…
これはVuetify2のVDatePickerでもあった事象でVuetify2のときはPropsにday-formatがあったので、以下のように書けば対処可能でした。
<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のドキュメントどおりだとブラウザのコンソールにエラーが出るので少し変えてます。
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')
<template>
<v-app>
<v-date-picker></v-date-picker>
</v-app>
</template>
日が消えた!でも何か色々おかしい!!
もうドキュメントには頼らない!ソースみる!!
ソースをみて各フォーマットを変更
落ち着いて、VuetifyのVDatePickerのソースをみます。
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でフォーマットが指定できることに気づく)
以下のように書き換えます。
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')
<template>
<v-app>
<v-date-picker></v-date-picker>
</v-app>
</template>
できた!
別解1(2024/1/30追記)
DateFnsAdapterを使う以外の方法がGitHubのプルリクエストにあったので、追記。
こっちの方が公式という感じかも…ちゃんと見ていなくて反省…
以下のように、VLocaleProviderを使いつつ、createVuetify関数で日のフォーマットを変えます。
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')
<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を使うだけで日本語化できます。
<template>
<v-app>
<v-locale-provider locale="ja">
<v-date-picker></v-date-picker>
</v-locale-provider>
</v-app>
</template>
う~ん、簡単!(あれ…この記事意味あったか?)
まとめ
以上がVuetify3のVDatePickerの日本語化の方法になります。
最終的なソースコードは以下に上げていますので、参考としてください。
参考文献
この記事は以下の情報を参考にして執筆しました。
- Date pickers 公式ページ
- Locale providers 公式ページ
- VDatePicker(GitHub)
- feat(date): add ability to pass custom formats #18375
- [Feature Request] VDatePicker should not have 日 character at each date when locale is ja. #18093
- Release v3.5.2・vuetifyjs/vuetify
- date-fns(GitHub)
- VuetifyのDate Pickerを日本語化したら"日"ってついてくる、やだキモい
Discussion