React + Next.js で、多言語対応したアプリケーションを開発している。
日本語から、英語などのラテン文字で記述する言語に切り替えた場合、文字が長くなり、レイアウトが崩れることがあるため、各言語でのレイアウトを簡潔に確認したい。
アプリケーション側にロケール切り替え機能を用意しているが、デザイナーなど非エンジニアでも確認しやすいよう、Storybookにロケール切り替えアイコンを追加する方法を調べたのでメモ。
環境
名前 | バージョン |
---|---|
React | 18.2.0 |
Next.js | 12.1.6 |
Storybook | 6.5.13 |
Storybook Addon Next | 1.6.10 |
Storybookへのアイコン追加方法
Storybookに、ロケール切り替えアイコンを追加したい。Storybook Addon Contextsやstorybook-addon-localeなどの拡張機能も見つかったが、公式ガイドのToolbars & globalsに、アイコン追加方法の記載があった。
.storybook/preview.js
に globalTypes
を宣言するだけで、アイコンを追加できる。 globalTypes
は、ストーリー内では context.globals
として参照可能。
また、Advanced usageに、そのものズバリなロケール切り替えのアイコン追加例が記載されている。
今回のユースケースであれば、 globalTypes
で十分なため、この方法を使用。
toolbar.iconで指定可能な文字列
以下の What icons are available for my toolbar or my addon?
に文字列の一覧、および実際にアイコンを表示するStorybookへのリンクがある。
記事作成時点でのStorybookへのリンクはこちら。
ロケールのNext.jsアプリケーションへの反映
Next.jsアプリケーションでStorybookを扱う際の問題を一括で対応してくれるアドオン、Storybook Addon Nextを使用している。
Next.jsではロケールを参照するのに useRouter
を用いるが、Storybook Addon Nextを用いるとRouterをモックしてくれる。
上記リンクの「Default Router」に記載があるが、モックされたRouterのlocaleは context?.globals?.locale
を参照しているため、 globalTypes
で locale
を変更できるようにすればいい。
const defaultRouter = { locale: context?.globals?.locale, ... }
ロケール切り替えアイコンの設定
.storybook/preview.js
に、以下を追加。
export const globalTypes = { locale: { name: 'Locale', description: 'Change locale', // アイコンホバー時に表示 defaultValue: 'ja-JP', toolbar: { icon: 'globe', items: [ { value: 'ja-JP', right: 'ja-JP', title: '日本語' }, { value: 'en-US', right: 'en-US', title: 'American English' }, { value: 'en-GB', right: 'en-GB', title: 'British English' }, ], }, }, }
これで、地球儀アイコンが追加される。クリックすると、以下のようにメニューが展開され、いずれかの言語をクリックすることで context.globals.locale
に toolbar.items
の value
で指定した値が設定される。
アイコンの表示位置について
globalTypes
で追加したアイコンは、拡張機能のアイコンの左に、区切り線なしで追加される。表示位置の調整や、セパレーターの追加などが可能かは未確認。
(調査中に、位置を調整したいというissueが対応不要でcloseされているのを見かけた気がするが、確認できなかった)
stories.tsx 内での globals の参照方法
今回は使わなかったが、Story関数の第2引数に globals
が設定されているため、Reactであれば以下の記述で各ストーリー内で globals
を参照できる。
import { Story } from '@storybook/react' import { MyComponent } from 'components/myComponent' export default { component: MyComponent } export const Default: Story = (_, { globals }) => ( <MyComponent locale={globals.locale} /> )
React以外でストーリーを記述している場合、以下を参照。
振り返り
「Storybook ロケール切り替え」あたりで検索すると、 react-i18next
や vue-i18n
の例ばかり出てくるので、面倒なのかと思い先延ばしにしていた。
いよいよ待ったなしになったので、本腰入れて調査したら、アドオンなど使わなくても設定できたので一安心。
また、さらっと流しているが、Storybookのロケール設定がNext.jsに反映されるのも、Storybook Addon Nextのおかげ。 next/image
動かない問題なども解消してくれるので、Next.jsアプリケーションでStorybookを使う時は必須だと思う、ありがたや。