🐛

MUI v5 DatePickerの使い方 その2 ~日本語化~

2022/03/31に公開
2

Vite+React+TypeScript 環境で MUI v5 DatePicker の使い方について、Tips的にまとめてみました。
今回はDatePickerの日本語化についての記事です。

MUI の導入方法についてはコチラ
Vite+React+TypeScript で、UIフレームワークにMUI(v5)を導入する。

MUI v5 DatePicker の記事一覧
MUI v5 DatePickerの使い方 その1 ~日付ライブラリの選定 から基本の使い方 まで~
MUI v5 DatePickerの使い方 その2 ~日本語化~

基本的な日本語化

date-fns の日本語ロケールを LocalizationProvider の locale に設定します。
選択した日付を「年月日」表示にするには、inputFormat や mask で設定します。

2022/05/25 変更
DataPicker が @mui/lab パッケージから @mui/x-date-pickers パッケージに変更になったことにより、一部コードを修正しました。
※ AdapterDateFns は @mui/x-date-pickers-pro に含まれていないため、有償版 @mui/x-date-pickers-pro を使用している場合は、無償版の mui/x-date-pickers も別途インストールする必要があります。

/* eslint-disable react/jsx-props-no-spreading */
import * as React from 'react'
import { Box, TextField } from '@mui/material'
import { LocalizationProvider, DatePicker } from '@mui/x-date-pickers-pro'
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'
+ import ja from 'date-fns/locale/ja'

export function DatePickerSample() {
  const [value, setValue] = React.useState<Date | null>(null)

  const handleChange = (newValue: Date | null) => {
    setValue(newValue)
  }

  return (
-   <LocalizationProvider dateAdapter={AdapterDateFns} >
+   <LocalizationProvider dateAdapter={AdapterDateFns} adapterLocale={ja}>
      <Box sx={{ m: 2, width: '25ch' }}>
        <DatePicker
          label="DatePicker"
          value={value}
          onChange={handleChange}
+          inputFormat='yyyy年MM月dd日'
+          mask='____年__月__日'
          renderInput={(params) => <TextField {...params} />}
        />

      </Box>
    </LocalizationProvider>
  )
}

年月の順番は残念ですが、日本語化はできています。

モバイルモードの表示も、惜しいです。


DataPicker を もっと細かく日本語化する

■ デスクトップ版の DatePicker の日本語化

左右矢印をホバーした際に「Previous month」と「Next month」が表示されます。

左矢印をホバーしたときのテキストはleftArrowButtonText に指定し
右矢印をホバーしたときのテキストはrightArrowButtonTextに指定します。

 <DatePicker
   label="DatePicker"
   value={value}
   onChange={handleChange}
   inputFormat="yyyy年MM月dd日"
   mask="____年__月__日"
+  leftArrowButtonText="前月を表示"
+  rightArrowButtonText="次月を表示"
   renderInput={(params) => <TextField {...params} />}
 />

■ モバイル版の DatePicker の日本語化


画面上部の「DATEPICKER」はtoolbarTitleでテキストを指定します。
画面下部の「CANCEL」はcancelTextで、「OK」はokTextでテキストを指定します。

  <DatePicker
    label="DatePicker"
    value={value}
    onChange={handleChange}
    inputFormat="yyyy年MM月dd日"
    mask="____年__月__日"
    leftArrowButtonText="前月を表示"
    rightArrowButtonText="次月を表示"
+    toolbarTitle="日付選択"
+    cancelText="キャンセル"
+    okText="選択"
    renderInput={(params) => <TextField {...params} />}
  />

選択した日付の書式をtoolbarFormatで指定します。

  <DatePicker
    label="DatePicker"
    value={value}
    onChange={handleChange}
    inputFormat="yyyy年MM月dd日"
    mask="____年__月__日"
    leftArrowButtonText="前月を表示"
    rightArrowButtonText="次月を表示"
    toolbarTitle="日付選択"
    cancelText="キャンセル"
    okText="選択"
+    toolbarFormat="yyyy年MM月dd日"
    renderInput={(params) => <TextField {...params} />}
  />

選択した日付の書式はいい感じになりましたが、フォントサイズが大きすぎるので、少し小さくしたいと思います。
DialogPropsの sx にスタイルを指定します。

import * as React from 'react'
import { Box, TextField } from '@mui/material'
import { LocalizationProvider, DatePicker } from '@mui/lab'
import AdapterDateFns from '@mui/lab/AdapterDateFns'
import ja from 'date-fns/locale/ja'

export function DatePickerSample() {
  const [value, setValue] = React.useState<Date | null>(null)

  const handleChange = (newValue: Date | null) => {
    setValue(newValue)
  }

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns} locale={ja}>
      <Box sx={{ m: 2, width: '25ch' }}>
        <DatePicker
          label="DatePicker"
          value={value}
          onChange={handleChange}
          inputFormat="yyyy年MM月dd日"
          mask="____年__月__日"
          leftArrowButtonText="前月を表示"
          rightArrowButtonText="次月を表示"
          toolbarTitle="日付選択"
          cancelText="キャンセル"
          okText="選択"
          toolbarFormat="yyyy年MM月dd日"
          renderInput={(params) => <TextField {...params} />}
+          DialogProps={{ sx: styles.mobiledialogprops }}
        />
      </Box>
    </LocalizationProvider>
  )
}

+ const styles = {
+  mobiledialogprops: {
+    '.PrivatePickersToolbar-dateTitleContainer .MuiTypography-root': {
+      fontSize: '1.5rem'
+    }
+  }
+}

ちょうどいい大きさになりました。

ヘッダの年月表示を修正する

ヘッダに表示されている「M月 yyyy」を「yyyy年M月」と修正します。

デスクトップ版:

モバイル版:

本来であればLocalizationProviderdateFormatsに表示書式を指定するといいようなのですが、
現時点のバージョン @mui/lab:v5.0.0-alpha.75 では正常に機能していません。

<LocalizationProvider dateAdapter={AdapterDateFns} locale={ja} dateFormats={{ monthAndYear: 'yyyy年MM月' }}

参考

そこで、css で強引に変更します。
デスクトップ版はPaperPropsに、モバイル版はDialogPropsにスタイルを指定します。

import * as React from 'react'
import { Box, TextField } from '@mui/material'

import { LocalizationProvider, DatePicker, MobileDatePicker } from '@mui/lab'

import AdapterDateFns from '@mui/lab/AdapterDateFns'
import ja from 'date-fns/locale/ja'

export function DatePickerSample() {
  const [value, setValue] = React.useState<Date | null>(null)

  const handleChange = (newValue: Date | null) => {
    setValue(newValue)
  }

  return (
    // <LocalizationProvider dateAdapter={AdapterDateFns} locale={ja} dateFormats={{ monthAndYear: 'yyyy MM' }} >
    <LocalizationProvider dateAdapter={AdapterDateFns} locale={ja}>
      <Box sx={{ m: 2, width: '25ch' }}>
        <DatePicker
          label="レスポンシブDatePicker"
          value={value}
          onChange={handleChange}
          inputFormat="yyyy年MM月dd日"
          mask="____年__月__日"
          leftArrowButtonText="前月を表示"
          rightArrowButtonText="次月を表示"
          toolbarTitle="日付選択"
          cancelText="キャンセル"
          okText="選択"
          toolbarFormat="yyyy年MM月dd日"
          renderInput={(params) => <TextField {...params} />}
+          PaperProps={{ sx: styles.paperprops }}
+          DialogProps={{ sx: styles.mobiledialogprops }}
        />
      </Box>
    </LocalizationProvider>
  )
}


const styles = {
  paperprops: {
    'div[role=presentation]': {
      display: 'flex',
      '& .PrivatePickersFadeTransitionGroup-root:first-of-type': {
        order: 2
      },
      '& .PrivatePickersFadeTransitionGroup-root:nth-of-type(2)': {
        order: 1,
        '& div::after':{
          content: '"年"'
        }
      },
      '& .MuiButtonBase-root': {
        order: 3
      }
    }
  },
  mobiledialogprops: {
    '.PrivatePickersToolbar-dateTitleContainer .MuiTypography-root': {
      fontSize: '1.5rem' // 選択した日付のフォントサイズを変更
    },
    'div[role=presentation]:first-of-type': {
      display: 'flex',
      '& .PrivatePickersFadeTransitionGroup-root:first-of-type': {
        order: 2
      },
      '& .PrivatePickersFadeTransitionGroup-root:nth-of-type(2)': {
        order: 1,
        '& > div::after': {
          content: '"年"'
        },
      },
      
      '& .MuiButtonBase-root': {
        order: 3
      }
    },
  }
}

ヘッダの表示が「yyyy年M月」になりました。

まとめ

強引ではありましたがなんとかDatePickerの日本語化対応ができました。
DatePickerはまだまだ正常に動作しない機能があり、今回の日本語化対応には予想以上に時間をとられてしまいました。

Discussion

rikusen0335rikusen0335

ほぼ1年前の記事に書くのもどうかと思いますが、v6から(?)残念な表示を改善することができるようになりました!

詳しくはこちらを:
https://next.mui.com/x/react-date-pickers/adapters-locale/#custom-toolbar-format

簡単な例もあげておきます

// date-fnsの場合
<MobileDateTimePicker 
  slotProps={{
    toolbar: { toolbarFormat: 'MMMM do', hidden: false }
  }}
/>

これで大体こんな感じです

フォーマットトークン(ここでいうMMMM do)はdate-fnsやdayjsなど、使うライブラリで違うので気をつけてください

また、LocalizationProviderを適切に設定しないと月とか日にはならないと思うのでそこも気をつけてください

良いコーディングを