瀏覽代碼

docs(ja): add Japanese docs for vuex 4.0 (#1980)

Co-authored-by: Kia King Ishii <kia.king.08@gmail.com>
Ryo_gk 4 年之前
父節點
當前提交
94d433ab34

+ 64 - 0
docs/.vitepress/config.js

@@ -14,6 +14,11 @@ module.exports = {
       title: 'Vuex',
       description: 'Vue.js 的中心化状态管理方案'
     },
+    '/ja/': {
+      lang: 'ja',
+      title: 'Vuex',
+      description: 'Vue.js のための集中状態管理'
+    },
     '/ptbr/': {
       lang: 'pt-BR',
       title: 'Vuex',
@@ -154,6 +159,65 @@ module.exports = {
         ]
       },
 
+      '/ja/': {
+        label: '日本語',
+        selectText: '言語',
+        editLinkText: 'GitHub 上でこのページを編集する',
+        lastUpdated: '最終更新日時',
+
+        nav: [
+          { text: 'ガイド', link: '/ja/guide/' },
+          { text: 'API リファレンス', link: '/ja/api/' },
+          { text: 'リリースノート', link: 'https://github.com/vuejs/vuex/releases' },
+          {
+            text: 'v4.x',
+            items: [
+              { text: 'v3.x', link: 'https://vuex.vuejs.org/ja' }
+            ]
+          }
+        ],
+
+        sidebar: [
+          {
+            text: 'はじめに',
+            children: [
+              { text: 'Vuex とは何か?', link: '/ja/' },
+              { text: 'インストール', link: '/ja/installation' },
+              { text: 'Vuex 入門', link: '/ja/guide/' }
+            ]
+          },
+          {
+            text: 'コアコンセプト',
+            children: [
+              { text: 'ステート', link: '/ja/guide/state' },
+              { text: 'ゲッター', link: '/ja/guide/getters' },
+              { text: 'ミューテーション', link: '/ja/guide/mutations' },
+              { text: 'アクション', link: '/ja/guide/actions' },
+              { text: 'モジュール', link: '/ja/guide/modules' }
+            ]
+          },
+          {
+            text: '高度な活用',
+            children: [
+              { text: 'アプリケーションの構造', link: '/ja/guide/structure' },
+              { text: 'Composition API', link: '/ja/guide/composition-api' },
+              { text: 'プラグイン', link: '/ja/guide/plugins' },
+              { text: '厳格モード', link: '/ja/guide/strict' },
+              { text: 'フォームの扱い', link: '/ja/guide/forms' },
+              { text: 'テスト', link: '/ja/guide/testing' },
+              { text: 'ホットリローディング', link: '/ja/guide/hot-reload' },
+              { text: 'TypeScript サポート', link: '/ja/guide/typescript-support' },
+            ]
+          },
+          {
+            text: '移行 ガイド',
+            children: [
+              { text: '3.x から 4.0 への移行', link: '/ja/guide/migrating-to-4-0-from-3-x' }
+            ]
+          }
+        ]
+      },
+
       '/ptbr/': {
         label: 'Português',
         selectText: 'Idiomas',

+ 390 - 0
docs/ja/api/index.md

@@ -0,0 +1,390 @@
+---
+sidebar: auto
+---
+
+# API リファレンス
+
+## Store
+
+### createStore
+
+- `createStore<S>(options: StoreOptions<S>): Store<S>`
+
+  新しいストアを作成します。
+
+  ```js
+  import { createStore } from 'vuex'
+
+  const store = createStore({ ...options })
+  ```
+
+## Store コンストラクタオプション
+
+### state
+
+- 型: `Object | Function`
+  ストアのための ルートステートオブジェクトです。 [詳細](../guide/state.md)
+
+  オブジェクトを返す関数を渡す場合、返されたオブジェクトはルートステートとして使用されます。これは特にモジュールの再利用のためにステートオブジェクトを再利用する場合に便利です。[詳細](../guide/modules.md#モジュールの再利用)
+
+### mutations
+
+- 型: `{ [type: string]: Function }`
+
+  ストアにミューテーションを登録します。ハンドラ関数は第 1 引数に `state` を常に受け取り(モジュール内で定義されていれば、モジュールのローカルステートを受け取り)、指定されていれば第 2 引数に `payload` を受け取ります。
+
+  [詳細](../guide/mutations.md)
+
+### actions
+
+- 型: `{ [type: string]: Function }`
+
+  ストアにアクションを登録します。ハンドラ関数は次のプロパティを持つ `context` オブジェクトを受け取ります。:
+
+  ```js
+  {
+    state,      // `store.state` と同じか、モジュール内にあればローカルステート
+    rootState,  // `store.state` と同じ。ただしモジュール内に限る
+    commit,     // `store.commit` と同じ
+    dispatch,   // `store.dispatch` と同じ
+    getters,    // `store.getters` と同じか、モジュール内にあればローカルゲッター
+    rootGetters // `store.getters` と同じ。ただしモジュール内に限る
+  }
+  ```
+
+  そして、第 2 引数の `payload` があれば、それを受け取ります。
+
+  [詳細](../guide/actions.md)
+
+### getters
+
+- 型: `{ [key: string]: Function }`
+
+  ストアにゲッターを登録します. ゲッター関数は次の引数を受け取ります:
+
+  ```
+  state,     // モジュール内で定義されていればモジュールのローカルステート
+  getters    // store.getters と同じ
+  ```
+
+  モジュールで定義されたときの仕様
+
+  ```
+  state,       // モジュールで定義された場合、モジュールのローカルステート
+  getters,     // 現在のモジュールのモジュールのローカルゲッター
+  rootState,   // グローバルステート
+  rootGetters  // 全てのゲッター
+  ```
+
+  登録されたゲッターは `store.getters` 上に公開されます。
+
+  [詳細](../guide/getters.md)
+
+### modules
+
+- 型: `Object`
+
+  サブモジュールを含む次のような形式のオブジェクトはストアにマージされます。
+
+  ```js
+  {
+    key: {
+      state,
+      namespaced?,
+      mutations?,
+      actions?,
+      getters?,
+      modules?
+    },
+    ...
+  }
+  ```
+
+  各モジュールは、ルートオプションに似た `state` と `mutations` を含むことができます。モジュールの状態は、モジュールのキーを使って、ストアのルートステートに結合されます。モジュールのミューテーションとゲッターは、第 1 引数としてルートステートの代わりに、モジュールのローカルステートだけを受け取り、モジュールのアクションの `context.state` もローカルステートを指すようになります。
+
+  [詳細](../guide/modules.md)
+
+### plugins
+
+- 型: `Array<Function>`
+
+  プラグイン関数の配列は、ストアに適用されます。このプラグインは、ストアだけを引数として受け取り、外部への永続化、ロギング、デバッギングのために、ミューテーションを監視するか、または、 websocket や observable のような外から渡されるデータのためにミューテーションをディスパッチします。
+
+  [詳細](../guide/plugins.md)
+
+### strict
+
+- 型: `boolean`
+- デフォルト: `false`
+
+  Vuex ストアを厳格モードにします。厳格モードでは、ミューテーションハンドラ以外で、 Vuex の状態の変更を行うと、エラーが投げられます。
+
+  [詳細](../guide/strict.md)
+
+### devtools
+
+- 型: `boolean`
+
+  特定の Vuex インスタンスに対して開発ツールをオン、またはオフにします。インスタンスに false を渡すと、開発ツールのプラグインを購読しないように Vuex ストアに伝えます。1 ページに複数のストアがある時に便利です。
+
+  ```js
+  {
+    devtools: false
+  }
+  ```
+
+## Store インスタンスプロパティ
+
+### state
+
+- 型: `Object`
+
+  ルートステート、読み取り専用です。
+
+### getters
+
+- 型: `Object`
+
+  登録されているゲッターを公開します。読み取り専用です。
+
+## Store インスタンスメソッド
+
+### commit
+
+-  `commit(type: string, payload?: any, options?: Object)`
+-  `commit(mutation: Object, options?: Object)`
+
+  ミューテーションをコミットします。`options` は[名前空間付きモジュール](../guide/modules.md#名前空間)で root なミューテーションにコミットできる `root: true` を持つことできます。[詳細](../guide/mutations.md)
+
+### dispatch
+
+-  `dispatch(type: string, payload?: any, options?: Object): Promise<any>`
+-  `dispatch(action: Object, options?: Object): Promise<any>`
+
+  アクションをディスパッチします。`options` は[名前空間付きモジュール](../guide/modules.md#名前空間)で root なアクションにディスパッチできる `root: true` を持つことできます。 すべてのトリガーされたアクションハンドラを解決するPromiseを返します。[詳細](../guide/actions.md)
+
+### replaceState
+
+-  `replaceState(state: Object)`
+
+  ストアのルートステートを置き換えます。これは、ステートのハイドレーションやタイムトラベルのためだけに利用すべきです。
+
+### watch
+
+-  `watch(fn: Function, callback: Function, options?: Object): Function`
+
+  `fn`が返す値をリアクティブに監視し、値が変わった時にコールバックを呼びます。`fn`は最初の引数としてストアのステートを、2番目の引数としてゲッターを受け取ります。 [Vue の`vm.$watch`メソッド](https://jp.vuejs.org/v2/api/#watch)と同じオプションをオプションのオブジェクトとして受け付けます。
+
+  監視を止める場合は、返された unwatch 関数を呼び出します。
+
+### subscribe
+
+-  `subscribe(handler: Function, options?: Object): Function`
+
+  ストアへのミューテーションを購読します。`handler` は、全てのミューテーションの後に呼ばれ、引数として、ミューテーション ディスクリプタとミューテーション後の状態を受け取ります。
+
+  ```js
+  const unsubscribe = store.subscribe((mutation, state) => {
+    console.log(mutation.type)
+    console.log(mutation.payload)
+  })
+  ```
+
+  デフォルトでは、新しい `handler` はチェーンの最後に登録されます。つまり、先に追加された他の `handler` が呼び出された後に実行されます。`prepend: true` を `options` に設定することで、`handler` をチェーンの最初に登録することができます。
+
+  ```js
+  store.subscribe(handler, { prepend: true })
+  ```
+
+  購読を停止するには、返された unsubscribe 関数呼び出します。
+
+  プラグインの中でもっともよく利用されます。[詳細](../guide/plugins.md)
+
+### subscribeAction
+
+-  `subscribeAction(handler: Function, options?: Object): Function`
+
+  スストアアクションを購読します。`handler` はディスパッチされたアクションごとに呼び出され、アクション記述子と現在のストア状態を引数として受け取ります:
+
+  ```js
+  const unsubscribe = store.subscribeAction((action, state) => {
+    console.log(action.type)
+    console.log(action.payload)
+  })
+  ```
+
+  デフォルトでは、新しい `handler` はチェーンの最後に登録されます。つまり、先に追加された他の `handler` が呼び出された後に実行されます。`prepend: true` を `options` に設定することで、`handler` をチェーンの最初に登録することができます。
+
+  ```js
+  store.subscribeAction(handler, { prepend: true })
+  ```
+
+  購読を停止するには、返された unsubscribe 関数を呼び出します。
+
+  `subscribeAction` は購読ハンドラがアクションディスパッチの*前 (before)*、または*後 (after)* に呼びだすべきかどうか(デフォルトの動作は、*before* です)指定することもできます。
+
+  ```js
+  store.subscribeAction({
+    before: (action, state) => {
+      console.log(`before action ${action.type}`)
+    },
+    after: (action, state) => {
+      console.log(`after action ${action.type}`)
+    }
+  })
+  ```
+
+  `subscribeAction` は `error` ハンドラを指定することもできます。このハンドラは、アクションディスパッチの中で投げられたエラーをキャッチすることができます。`error` ハンドラは投げられた `error` オブジェクトを第 3 引数として受け取ります。
+
+  ```js
+  store.subscribeAction({
+    error: (action, state, error) => {
+      console.log(`error action ${action.type}`)
+      console.error(error)
+    }
+  })
+  ```
+
+  `subscribeAction` メソッドはプラグインで最も一般的に使用されます。[詳細](../guide/plugins.md)
+
+### registerModule
+
+-  `registerModule(path: string | Array<string>, module: Module, options?: Object)`
+
+   動的なモジュールを登録します。[詳細](../guide/modules.md#dynamic-module-registration)
+
+  `options` は前の状態を保存する `preserveState: true` を持つことができます。サーバサイドレンダリングに役立ちます。
+
+### unregisterModule
+
+-  `unregisterModule(path: string | Array<string>)`
+
+  動的なモジュールを解除します。[詳細](../guide/modules.md#dynamic-module-registration)
+
+### hasModule
+
+- `hasModule(path: string | Array<string>): boolean`
+
+  動的なモジュールがすでに登録されているかどうかを確認します。[詳細](../guide/modules.md#dynamic-module-registration)
+
+### hotUpdate
+
+-  `hotUpdate(newOptions: Object)`
+
+  新しいアクションとミューテーションをホットスワップします。[詳細](../guide/hot-reload.md)
+
+## コンポーネントをバインドするヘルパー
+
+### mapState
+
+-  `mapState(namespace?: string, map: Array<string> | Object<string | function>): Object`
+
+  ストアのサブツリーを返すコンポーネントの computed オプションを作成します。[詳細](../guide/state.md#the-mapstate-helper)
+
+  第 1 引数は、オプションで名前空間文字列にすることができます。[詳細](../guide/modules.md#binding-helpers-with-namespace)
+
+  第 2 引数のオブジェクトのメンバーには関数 `function(state: any)` を指定できます。
+
+### mapGetters
+
+-  `mapGetters(namespace?: string, map: Array<string> | Object<string>): Object`
+
+  ゲッターの評価後の値を返すコンポーネントの computed オプションを作成します。[詳細](../guide/getters.md#the-mapgetters-helper)
+
+  第 1 引数は、オプションで名前空間文字列にすることができます。[詳細](../guide/modules.md#binding-helpers-with-namespace)
+
+### mapActions
+
+-  `mapActions(namespace?: string, map: Array<string> | Object<string | function>): Object`
+
+  アクションをディスパッチするコンポーネントの methods オプションを作成します。[詳細](../guide/actions.md#dispatching-actions-in-components)
+
+  第 1 引数は、オプションで名前空間文字列にすることができます。[詳細](../guide/modules.md#binding-helpers-with-namespace)
+
+  第 2 引数のオブジェクトのメンバーには関数 `function(dispatch: function, ...args: any[])` を指定できます。
+
+### mapMutations
+
+-  `mapMutations(namespace?: string, map: Array<string> | Object<string | function>): Object`
+
+  ミューテーションをコミットするコンポーネントの methods オプションを作成します。[詳細](../guide/mutations.md#commiting-mutations-in-components)
+
+  第 1 引数は、オプションで名前空間文字列にすることができます。[詳細](../guide/modules.md#binding-helpers-with-namespace)
+
+  第 2 引数のオブジェクトのメンバーには関数 `function(commit: function, ...args: any[])` を指定できます。
+
+### createNamespacedHelpers
+
+-  `createNamespacedHelpers(namespace: string): Object`
+
+  名前空間付けられたコンポーネントバインディングのヘルパーを作成します。返されるオブジェクトは指定された名前空間にバインドされた `mapState`、`mapGetters`、`mapActions` そして `mapMutations` が含まれます。[詳細はこちら](../guide/modules.md#binding-helpers-with-namespace)
+
+## Composable 関数
+
+### useStore
+
+- `useStore<S = any>(injectKey?: InjectionKey<Store<S>> | string): Store<S>;`
+
+  `setup` フックの中で呼ばれた時に、Vue App インスタンスにインストールされたストアを取得します。Composition API を使用する時、このメソッドを呼ぶことでストアを取得することができます。
+
+  ```js
+  import { useStore } from 'vuex'
+
+  export default {
+    setup () {
+      const store = useStore()
+    }
+  }
+  ```
+
+  TypeScript ユーザーは、 `InjectionKey` を使って型付けされたストアを取得することができます。そのためには、ストアインスタンスを Vue App インスタンスにインストールする時、`InjectionKey` を定義してストアと一緒に渡す必要があります。
+
+  まず、Vue の `InjectionKey` インターフェースを使って、 `InjectionKey` を宣言します。
+
+  ```ts
+  // store.ts
+  import { InjectionKey } from 'vue'
+  import { createStore, Store } from 'vuex'
+
+  export interface State {
+    count: number
+  }
+
+  export const key: InjectionKey<Store<State>> = Symbol()
+
+  export const store = createStore<State>({
+    state: {
+      count: 0
+    }
+  })
+  ```
+
+  次に、定義したキーを `app.use` メソッドの第2引数に渡します。
+
+  ```ts
+  // main.ts
+  import { createApp } from 'vue'
+  import { store, key } from './store'
+
+  const app = createApp({ ... })
+
+  app.use(store, key)
+
+  app.mount('#app')
+  ```
+
+  最後に、`useStore` 関数にキーを渡すことで、型付けされたストアインスタンスを取得することができます。
+
+  ```ts
+  // vue component 内
+  import { useStore } from 'vuex'
+  import { key } from './store'
+
+  export default {
+    setup () {
+      const store = useStore(key)
+
+      store.state.count // number として型付け
+    }
+  }
+  ```

+ 179 - 0
docs/ja/guide/actions.md

@@ -0,0 +1,179 @@
+# アクション
+
+<div class="scrimba"><a href="https://scrimba.com/p/pnyzgAP/c6ggR3cG" target="_blank" rel="noopener noreferrer">Scrimba のレッスンを試す</a></div>
+
+アクションはミューテーションと似ていますが、下記の点で異なります:
+
+- アクションは、状態を変更するのではなく、ミューテーションをコミットします。
+- アクションは任意の非同期処理を含むことができます。
+
+シンプルなアクションを登録してみましょう:
+
+``` js
+const store = createStore({
+  state: {
+    count: 0
+  },
+  mutations: {
+    increment (state) {
+      state.count++
+    }
+  },
+  actions: {
+    increment (context) {
+      context.commit('increment')
+    }
+  }
+})
+```
+
+アクションハンドラはストアインスタンスのメソッドやプロパティのセットと同じものを呼び出せるコンテキストオブジェクトを受け取ります。したがって `context.commit` を呼び出すことでミューテーションをコミットできます。あるいは `context.state` や `context.getters` で、状態やゲッターにアクセスできます。他のアクションも `context.dispatch` で呼ぶこともできます。なぜコンテキストオブジェクトがストアインスタンスそのものではないのかは、後ほど[モジュール](modules.md)で説明します。
+
+実際にはコードを少しシンプルにするために ES2015 の[引数分割束縛(argument destructuring)](https://github.com/lukehoban/es6features#destructuring)がよく使われます(特に `commit` を複数回呼び出す必要があるとき):
+
+``` js
+actions: {
+  increment ({ commit }) {
+    commit('increment')
+  }
+}
+```
+
+## アクションのディスパッチ
+
+アクションは `store.dispatch` がトリガーとなって実行されます:
+
+``` js
+store.dispatch('increment')
+```
+
+これは一見ばかげて見えるかもしれません。つまり、カウントをインクリメントしたいときに、どうして直接 `store.commit('increment')` を呼び出してミューテーションをコミットしないのか、と。**ミューテーションは同期的でなければならない**というのを覚えていますか?アクションはそうではありません。アクションの中では**非同期**の操作を行うことができます。
+
+``` js
+actions: {
+  incrementAsync ({ commit }) {
+    setTimeout(() => {
+      commit('increment')
+    }, 1000)
+  }
+}
+```
+
+アクションはペイロード形式とオブジェクトスタイルのディスパッチをサポートします:
+
+``` js
+// ペイロードを使ってディスパッチする
+store.dispatch('incrementAsync', {
+  amount: 10
+})
+
+// オブジェクトを使ってディスパッチする
+store.dispatch({
+  type: 'incrementAsync',
+  amount: 10
+})
+```
+
+より実践的な例として、ショッピングカートをチェックアウトするアクションを挙げます。このアクションは**非同期な API の呼び出し**と、**複数のミューテーションのコミット**をします:
+
+``` js
+actions: {
+  checkout ({ commit, state }, products) {
+    // 現在のカート内の商品を保存する
+    const savedCartItems = [...state.cart.added]
+    // チェックアウトのリクエストを送信し、楽観的にカート内をクリアする
+    commit(types.CHECKOUT_REQUEST)
+    // shop API は成功時のコールバックと失敗時のコールバックを受け取る
+    shop.buyProducts(
+      products,
+      // 成功時の処理
+      () => commit(types.CHECKOUT_SUCCESS),
+      // 失敗時の処理
+      () => commit(types.CHECKOUT_FAILURE, savedCartItems)
+    )
+  }
+}
+```
+
+一連の非同期の処理を実行しつつ、ミューテーションのコミットによってのみ副作用(状態の変更)を与えていることに注意してください。
+
+## コンポーネント内でのアクションのディスパッチ
+
+`this.$store.dispatch('xxx')` でコンポーネント内でアクションをディスパッチできます。あるいはコンポーネントのメソッドを `store.dispatch` にマッピングする `mapActions` ヘルパーを使うこともできます(ルートの `store` の注入が必要です):
+
+``` js
+import { mapActions } from 'vuex'
+
+export default {
+  // ...
+  methods: {
+    ...mapActions([
+      'increment', // `this.increment()` を `this.$store.dispatch('increment')` にマッピングする('increment')`
+
+      // `mapActions` もペイロードをサポートする:
+      'incrementBy' // `this.incrementBy(amount)` を `this.$store.dispatch('incrementBy', amount)` にマッピングする
+    ]),
+    ...mapActions({
+      add: 'increment' // `this.add()` を `this.$store.dispatch('increment')` にマッピングする
+    })
+  }
+}
+```
+
+## アクションを構成する
+
+アクションはしばしば非同期処理を行いますが、アクションが完了したことをどうやって知れば良いのでしょう?そしてもっと重要なことは、さらに複雑な非同期処理を取り扱うために、どうやって複数のアクションを構成させるかということです。
+
+まず知っておくべきことは `store.dispatch` がトリガーされたアクションハンドラによって返された Promise を処理できることと、`store.dispatch` もまた Promise を返すことです。
+
+``` js
+actions: {
+  actionA ({ commit }) {
+    return new Promise((resolve, reject) => {
+      setTimeout(() => {
+        commit('someMutation')
+        resolve()
+      }, 1000)
+    })
+  }
+}
+```
+
+すると次のようにできます:
+
+``` js
+store.dispatch('actionA').then(() => {
+  // ...
+})
+```
+
+また別のアクションで下記のように書くと:
+
+``` js
+actions: {
+  // ...
+  actionB ({ dispatch, commit }) {
+    return dispatch('actionA').then(() => {
+      commit('someOtherMutation')
+    })
+  }
+}
+```
+
+最終的に [async / await](https://tc39.github.io/ecmascript-asyncawait/) を使用することで、次のようにアクションを組み合わせることができます:
+
+``` js
+// `getData()` と `getOtherData()` が Promise を返すことを想定している
+
+actions: {
+  async actionA ({ commit }) {
+    commit('gotData', await getData())
+  },
+  async actionB ({ dispatch, commit }) {
+    await dispatch('actionA') // `actionA` が完了するのを待機する
+    commit('gotOtherData', await getOtherData())
+  }
+}
+```
+
+> `store.dispatch` で異なるモジュール内の複数のアクションハンドラをトリガーすることができます。そのようなケースでは、全てのトリガーされたハンドラが解決されたときに解決する Promise が戻り値として返ってくることになります。

+ 62 - 0
docs/ja/guide/composition-api.md

@@ -0,0 +1,62 @@
+# Composition API
+
+`setup` フックの中でストアにアクセスするには、`useStore` 関数を呼び出します。これは、Option API を使って、コンポーネント内で `this.$store` を取得するのと同等です。
+
+```js
+import { useStore } from 'vuex'
+
+export default {
+  setup () {
+    const store = useStore()
+  }
+}
+```
+
+## ステートとゲッターへのアクセス
+
+ステートやゲッターにアクセスするためには、リアクティビティを保持するために `computed` による参照を作成する必要があります。これは、Option API を使って、算出プロパティを作成するのと同じことです。
+
+```js
+import { computed } from 'vue'
+import { useStore } from 'vuex'
+
+export default {
+  setup () {
+    const store = useStore()
+
+    return {
+      // computed 関数のステートにアクセスします
+      count: computed(() => store.state.count),
+
+      // computed 関数のゲッターにアクセスします
+      double: computed(() => store.getters.double)
+    }
+  }
+}
+```
+
+## ミューテーションとアクションへのアクセス
+
+ミューテーションとアクションにアクセスするには、`setup` フック内で `commit` と `dispatch` 関数を呼び出します。
+
+```js
+import { useStore } from 'vuex'
+
+export default {
+  setup () {
+    const store = useStore()
+
+    return {
+      // ミューテーションにアクセスする
+      increment: () => store.commit('increment'),
+
+      // アクションにアクセスする
+      asyncIncrement: () => store.dispatch('asyncIncrement')
+    }
+  }
+}
+```
+
+## Composition API での実装例
+
+Vuex と Vue の Composition API を利用したアプリケーションの例は、[Composition API example](https://github.com/vuejs/vuex/tree/4.0/examples/composition) をご覧ください。

+ 61 - 0
docs/ja/guide/forms.md

@@ -0,0 +1,61 @@
+# フォームの扱い
+
+<div class="scrimba"><a href="https://scrimba.com/p/pnyzgAP/cqKRgEC9" target="_blank" rel="noopener noreferrer">Scrimba のレッスンを試す</a></div>
+
+厳格モードで Vuex を使用するとき、Vuex に属する状態の一部で `v-model` を使用するのは少しトリッキーです:
+
+``` html
+<input v-model="obj.message">
+```
+
+`obj` がストアからオブジェクトを返す算出プロパティ (computed property) と仮定すると、`v-model` は input でユーザーが入力するとき、直接 `obj.message` を変更します。厳格モードでは、この変更は明示的に Vuex のミューテーションハンドラ内部で処理されていないため、エラーを投げます。
+
+それに対処するための "Vuex way" は、`<input>` の値をバインディングし、`input` または `change` イベントでアクションを呼び出すことです:
+
+``` html
+<input :value="message" @input="updateMessage">
+```
+``` js
+// ...
+computed: {
+  ...mapState({
+    message: state => state.obj.message
+  })
+},
+methods: {
+  updateMessage (e) {
+    this.$store.commit('updateMessage', e.target.value)
+  }
+}
+```
+
+ミューテーションのハンドラは以下のようになります:
+
+``` js
+// ...
+mutations: {
+  updateMessage (state, message) {
+    state.obj.message = message
+  }
+}
+```
+
+## 双方向算出プロパティ
+
+確かに、上記の例は単純な `v-model` と ローカルステートよりもかなり冗長で、`v-model` のいくつかの有用な機能が使えません。代わりに、セッターで双方向算出プロパティを使うアプローチがあります。
+
+``` html
+<input v-model="message">
+```
+``` js
+computed: {
+  message: {
+    get () {
+      return this.$store.state.obj.message
+    },
+    set (value) {
+      this.$store.commit('updateMessage', value)
+    }
+  }
+}
+```

+ 121 - 0
docs/ja/guide/getters.md

@@ -0,0 +1,121 @@
+# ゲッター
+
+<div class="scrimba"><a href="https://scrimba.com/p/pnyzgAP/c2Be7TB" target="_blank" rel="noopener noreferrer">Scrimba のレッスンを試す</a></div>
+
+例えば項目のリストをフィルタリングしたりカウントするときのように、ストアの状態を算出したいときがあります。
+
+``` js
+computed: {
+  doneTodosCount () {
+    return this.$store.state.todos.filter(todo => todo.done).length
+  }
+}
+```
+
+もしこの関数を複数のコンポーネントで利用したくなったら、関数をコピーするか、あるいは関数を共用のヘルパーに切り出して複数の場所でインポートする必要があります。しかし、どちらも理想的とはいえません。
+
+Vuex を利用するとストア内に "ゲッター" を定義することができます。それらをストアの算出プロパティと考えることができます。
+
+::: warning 警告
+Vue 3.0 では、ゲッターの結果は算出プロパティのように**キャッシュされません**。これは既知の問題で、Vue 3.1 がリリースされる必要があります。詳細は [PR #1878](https://github.com/vuejs/vuex/pull/1883) をご確認ください。
+:::
+
+ゲッターは第1引数として、state を受け取ります:
+
+``` js
+const store = createStore({
+  state: {
+    todos: [
+      { id: 1, text: '...', done: true },
+      { id: 2, text: '...', done: false }
+    ]
+  },
+  getters: {
+    doneTodos (state) {
+      return state.todos.filter(todo => todo.done)
+    }
+  }
+})
+```
+
+## プロパティスタイルアクセス
+
+ゲッターは `store.getters` オブジェクトから取り出され、プロパティとしてアクセスすることができます:
+
+``` js
+store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
+```
+
+ゲッターは第2引数として他のゲッターを受け取ります:
+
+``` js
+getters: {
+  // ...
+  doneTodosCount (state, getters) {
+    return getters.doneTodos.length
+  }
+}
+```
+
+``` js
+store.getters.doneTodosCount // -> 1
+```
+
+どのコンポーネントの内部でも簡単にゲッターを利用することができます:
+
+``` js
+computed: {
+  doneTodosCount () {
+    return this.$store.getters.doneTodosCount
+  }
+}
+```
+
+プロパティとしてアクセスされるゲッターは Vue のリアクティブシステムの一部としてキャッシュされるという点に留意してください。
+
+## メソッドスタイルアクセス
+
+関数を返り値にすることで、ゲッターに引数を渡すこともできます。これは特にストアの中の配列を検索する時に役立ちます:
+```js
+getters: {
+  // ...
+  getTodoById: (state) => (id) => {
+    return state.todos.find(todo => todo.id === id)
+  }
+}
+```
+
+``` js
+store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
+```
+
+メソッドによってアクセスされるゲッターは呼び出す度に実行され、その結果はキャッシュされない点に留意してください。
+
+## `mapGetters` ヘルパー
+
+`mapGetters` ヘルパーはストアのゲッターをローカルの算出プロパティにマッピングさせます:
+
+``` js
+import { mapGetters } from 'vuex'
+
+export default {
+  // ...
+  computed: {
+    // ゲッターを、スプレッド演算子(object spread operator)を使って computed に組み込む
+    ...mapGetters([
+      'doneTodosCount',
+      'anotherGetter',
+      // ...
+    ])
+  }
+}
+```
+
+ゲッターを異なる名前でマッピングさせたいときはオブジェクトを使います:
+
+``` js
+...mapGetters({
+  // `this.doneCount` を `this.$store.getters.doneTodosCount` にマッピングさせる
+  doneCount: 'doneTodosCount'
+})
+```

+ 85 - 0
docs/ja/guide/hot-reload.md

@@ -0,0 +1,85 @@
+# ホットリローディング
+
+Vuex は webpack の [Hot Module Replacement API](https://webpack.js.org/guides/hot-module-replacement/) を使用することで、アプリケーションの開発を行っている間のミューテーション、モジュール、アクション、ゲッターのホットリローディングをサポートします。Browserify では [browserify-hmr](https://github.com/AgentME/browserify-hmr/) プラグインを使用することができます。
+
+ミューテーションとモジュールのホットリローディングのために、`store.hotUpdate()`  API メソッドを利用する必要があります:
+
+``` js
+// store.js
+import { createStore } from 'vuex'
+import mutations from './mutations'
+import moduleA from './modules/a'
+
+const state = { ... }
+
+const store = createStore({
+  state,
+  mutations,
+  modules: {
+    a: moduleA
+  }
+})
+
+if (module.hot) {
+  // ホットモジュールとしてアクションとモジュールを受け付けます
+  module.hot.accept(['./mutations', './modules/a'], () => {
+    // 更新されたモジュールをインポートする
+    // babel 6 のモジュール出力のため、ここでは .default を追加しなければならない
+    const newMutations = require('./mutations').default
+    const newModuleA = require('./modules/a').default
+    // 新しいモジュールとミューテーションにスワップ
+    store.hotUpdate({
+      mutations: newMutations,
+      modules: {
+        a: newModuleA
+      }
+    })
+  })
+}
+```
+
+ホットリローディングを試したい場合は、[counter-hot example](https://github.com/vuejs/vuex/tree/dev/examples/counter-hot)をチェックアウトしてください。
+
+## 動的モジュールホットリローディング
+
+もしストアでモジュールだけを使用している場合には、`require.context` を使って全てのモジュールを動的に読み込むこともできます。
+
+```js
+// store.js
+import { createStore } from 'vuex'
+
+// 全てのモジュールをロードする
+function loadModules() {
+  const context = require.context("./modules", false, /([a-z_]+)\.js$/i)
+
+  const modules = context
+    .keys()
+    .map((key) => ({ key, name: key.match(/([a-z_]+)\.js$/i)[1] }))
+    .reduce(
+      (modules, { key, name }) => ({
+        ...modules,
+        [name]: context(key).default
+      }),
+      {}
+    )
+
+  return { context, modules }
+}
+
+const { context, modules } = loadModules()
+
+const store = createStore({
+  modules
+})
+
+if (module.hot) {
+  // モジュールに変更があった場合にホットリロードする
+  module.hot.accept(context.id, () => {
+    const { modules } = loadModules()
+
+    store.hotUpdate({
+      modules
+    })
+  })
+}
+```

+ 66 - 0
docs/ja/guide/index.md

@@ -0,0 +1,66 @@
+# Vuex 入門
+
+<div class="scrimba"><a href="https://scrimba.com/p/pnyzgAP/cMPa2Uk" target="_blank" rel="noopener noreferrer">Scrimba のレッスンを試す</a></div>
+
+Vuex アプリケーションの中心にあるものは**ストア**です。"ストア" は、基本的にアプリケーションの **状態(state)** を保持するコンテナです。単純なグローバルオブジェクトとの違いが 2つあります。
+
+1. Vuex ストアはリアクティブです。Vue コンポーネントがストアから状態を取り出すとき、もしストアの状態が変化したら、ストアはリアクティブかつ効率的に更新を行います。
+
+2. ストアの状態を直接変更することはできません。明示的に**ミューテーションをコミットする**ことによってのみ、ストアの状態を変更します。これによって、全ての状態の変更について追跡可能な記録を残すことが保証され、ツールでのアプリケーションの動作の理解を助けます。
+
+## シンプルなストア
+
+:::tip 注意
+私たちは、このドキュメントのコード例に ES2015 のシンタックスを利用しています。 もし触れたことがなければ、[ぜひ触れてください](https://babeljs.io/docs/learn-es2015/)!
+:::
+
+Vuex を[インストール](../installation.md) してから、ストアをつくってみましょう。Vuex ストアの作成は、とても簡単です。ストアオブジェクトの初期状態と、いくつかのミューテーションを準備するだけです。
+
+```js
+import { createApp } from 'vue'
+import { createStore } from 'vuex'
+
+// 新しいストアインスタンスを作成します
+const store = createStore({
+  state () {
+    return {
+      count: 0
+    }
+  },
+  mutations: {
+    increment (state) {
+      state.count++
+    }
+  }
+})
+
+const app = createApp({ /* ルートコンポーネント */ })
+
+// プラグインとしてストアインスタンスをインストールします
+app.use(store)
+```
+
+これで `store.state` でストアオブジェクトの状態を参照でき、また `store.commit` メソッドで状態の変更を行うことができます。
+
+```js
+store.commit('increment')
+
+console.log(store.state.count) // -> 1
+```
+
+Vue コンポーネントでは、`this.$store` としてストアにアクセスできます。それでは、コンポーネントのメソッドを使ってミューテーションをコミットしてみましょう。
+
+```js
+methods: {
+  increment() {
+    this.$store.commit('increment')
+    console.log(this.$store.state.count)
+  }
+}
+```
+
+そして `store.state.count` を直接変更する代わりにミューテーションをコミットする理由は、状態の変更を明確に追跡したいからです。このシンプルな規約は、あなたのコードの意図をさらに明確にし、コードを読んだ時にアプリケーションの状態の変更について、論理的に考えることができるようにします。加えて、私たちに全ての変更のログを取ったり、状態のスナップショットを取ったり、タイムトラベルデバッグを行うようなツールを実装する余地を与えてくれます。
+
+ストアオブジェクトの状態はリアクティブなので、ストアの状態をコンポーネント内で使うには算出プロパティ内でただ状態を返せば良いです。コンポーネントメソッドでミューテーションをコミットすることによって状態の変更を行います。
+
+これから Vuex のコアコンセプトについて詳しく説明していきます。まずは[状態(state)](state.md)からはじめましょう。

+ 116 - 0
docs/ja/guide/migrating-to-4-0-from-3-x.md

@@ -0,0 +1,116 @@
+# 3.x から 4.0 への移行
+
+ほとんどすべての Vuex 4 の API は、Vuex 3 から変更されていません。しかし、修正が必要な破壊的変更がいくつかあります。
+
+- [破壊的変更](#破壊的変更)
+  - [インストール手順](#インストール手順)
+  - [TypeScript サポート](#typescript-サポート)
+  - [バンドルが Vue 3 に対応しました](#バンドルが-vue-3-に対応しました)
+  - ["createLogger" 関数はコアモジュールからエクスポートされます](#createlogger-関数はコアモジュールからエクスポートされます)
+- [新機能](#新機能)
+  - [新しい "useStore" 合成関数](#新しい-usestore-合成関数)
+
+## 破壊的変更
+
+### インストール手順
+
+新しい Vue 3 の初期化の手順に合わせて、Vuex のインストール手順が変更されました。新しいストアを作成するには、新しく導入された createStore 関数を使用することが推奨されます。
+
+```js
+import { createStore } from 'vuex'
+
+export const store = createStore({
+  state () {
+    return {
+      count: 1
+    }
+  }
+})
+```
+
+VueインスタンスにVuexをインストールするには、Vuexではなく`store`を渡します。
+
+```js
+import { createApp } from 'vue'
+import { store } from './store'
+import App from './App.vue'
+
+const app = createApp(App)
+
+app.use(store)
+
+app.mount('#app')
+```
+
+:::tip 注意
+厳密にはこれは破壊的変更ではなく、まだ `new Store(...)` 構文を使用することができますが、Vue 3 と Vue Router Next に合わせるためにこの方法を推奨します。
+:::
+
+### TypeScript サポート
+
+Vuex 4 は、[issue #994](https://github.com/vuejs/vuex/issues/994) を解決するために、Vue コンポーネント内の `this.$store` のグローバルな型付けを削除します。TypeScript で使用する場合は、独自のモジュール拡張を宣言する必要があります。
+
+次のコードをあなたのプロジェクトに配置して、`this.$store` が正しく型付けされるようにしてください。
+
+```ts
+// vuex-shim.d.ts
+
+import { ComponentCustomProperties } from 'vue'
+import { Store } from 'vuex'
+
+declare module '@vue/runtime-core' {
+  // ストアのステートを宣言する
+  interface State {
+    count: number
+  }
+
+  interface ComponentCustomProperties {
+    $store: Store<State>
+  }
+}
+```
+
+詳細は、[TypeScript サポート](./typescript-support) セクションをご覧ください.
+
+### バンドルが Vue 3 に対応しました
+
+以下のバンドルは、Vue 3 のバンドルに合わせて生成されます。
+
+- `vuex.global(.prod).js`
+  - ブラウザの `<script src="...">` で直接使用します。Vuexのグローバルを公開しています。
+  - グローバルビルドは UMD ではなく IIFE としてビルドされており、`<script src="...">` での直接使用のみを想定しています。
+  - ハードコードされた prod/dev ブランチが含まれており、prod ビルドはあらかじめ minify されています。本番環境では、`.prod.js` ファイルを使用してください。
+- `vuex.esm-browser(.prod).js`
+  - ネイティブの ES モジュールのインポート(`<script type="module">` でブラウザをサポートするモジュールを含む)で使用されます。
+- `vuex.esm-bundler.js`
+  - `webpack`, `rollup`, `parcel` などのバンドラーで使用されます。
+  - `process.env.NODE_ENV` のガードを持つ prod/dev ブランチを残します(バンドラーで置き換える必要があります)。
+  - minify されたビルドは出荷されません(バンドル後に他のコードと一緒に行われます)。
+- `vuex.cjs.js`
+  - Node.js のサーバーサイドレンダリングで、`require()`を使って使用されます。
+
+### "createLogger" 関数はコアモジュールからエクスポートされます
+
+Vuex 3では、`createLogger` 関数は `vuex/dist/logger` からエクスポートされていましたが、現在は core パッケージに含まれています。この関数は `vuex` パッケージから直接インポートする必要があります。
+
+```js
+import { createLogger } from 'vuex'
+```
+
+## 新機能
+
+### 新しい "useStore" 合成関数
+
+Vuex 4 では、Composition API でストアを操作するための新しい API が導入されました。合成関数の `useStore` を使って、コンポーネントの `setup` フック内でストアを取得することができます。
+
+```js
+import { useStore } from 'vuex'
+
+export default {
+  setup () {
+    const store = useStore()
+  }
+}
+```
+
+詳細は、[Composition API](./composition-api)のセクションをご覧ください。

+ 342 - 0
docs/ja/guide/modules.md

@@ -0,0 +1,342 @@
+# モジュール
+
+<div class="scrimba"><a href="https://scrimba.com/p/pnyzgAP/cqKK4psq" target="_blank" rel="noopener noreferrer">Scrimba のレッスンを試す</a></div>
+
+単一ステートツリーを使うため、アプリケーションの全ての状態は、一つの大きなストアオブジェクトに内包されます。しかしながら、アプリケーションが大きくなるにつれて、ストアオブジェクトは膨れ上がってきます。
+
+そのような場合に役立てるため Vuex ではストアを**モジュール**に分割できるようになっています。それぞれのモジュールは、モジュール自身の状態(state)、ミューテーション、アクション、ゲッター、モジュールさえも内包できます(モジュールをネストできます)- トップからボトムまでフラクタル構造です:
+
+```js
+const moduleA = {
+  state: () => ({ ... }),
+  mutations: { ... },
+  actions: { ... },
+  getters: { ... }
+}
+
+const moduleB = {
+  state: () => ({ ... }),
+  mutations: { ... },
+  actions: { ... }
+}
+
+const store = createStore({
+  modules: {
+    a: moduleA,
+    b: moduleB
+  }
+})
+
+store.state.a // -> `moduleA` のステート
+store.state.b // -> `moduleB` のステート
+```
+
+## モジュールのローカルステート
+
+モジュールのミューテーションやゲッターの中では、渡される第 1 引数は**モジュールのローカルステート**です。
+
+```js
+const moduleA = {
+  state: () => ({
+    count: 0
+  }),
+  mutations: {
+    increment (state) {
+      // `state` はモジュールのローカルステート
+      state.count++
+    }
+  },
+  getters: {
+    doubleCount (state) {
+      return state.count * 2
+    }
+  }
+}
+```
+
+同様に、モジュールのアクションの中では `context.state` はローカルステートにアクセスでき、ルートのステートは `context.rootState` でアクセスできます:
+
+```js
+const moduleA = {
+  // ...
+  actions: {
+    incrementIfOddOnRootSum ({ state, commit, rootState }) {
+      if ((state.count + rootState.count) % 2 === 1) {
+        commit('increment')
+      }
+    }
+  }
+}
+```
+
+また、モジュールのゲッターの中では、ルートのステートは第3引数でアクセスできます:
+
+```js
+const moduleA = {
+  // ...
+  getters: {
+    sumWithRootCount (state, getters, rootState) {
+      return state.count + rootState.count
+    }
+  }
+}
+```
+
+## 名前空間
+
+デフォルトでは、モジュール内部のアクション、ミューテーション、そしてゲッターは**グローバル名前空間**の元で登録されます - これにより、複数のモジュールが同じミューテーション/アクションタイプに反応することができます。
+
+モジュールをより自己完結型にまた再利用可能なものにしたい場合は、それを `namespaced: true` によって名前空間に分けることができます。モジュールが登録されると、そのゲッター、アクション、およびミューテーションのすべてが、モジュールが登録されているパスに基づいて自動的に名前空間に入れられます。例えば:
+
+```js
+const store = createStore({
+  modules: {
+    account: {
+      namespaced: true,
+
+      // モジュールのアセット
+      state: () => ({ ... }), // モジュールステートはすでにネストされており、名前空間のオプションによって影響を受けません
+      getters: {
+        isAdmin () { ... } // -> getters['account/isAdmin']
+      },
+      actions: {
+        login () { ... } // -> dispatch('account/login')
+      },
+      mutations: {
+        login () { ... } // -> commit('account/login')
+      },
+
+      // ネストされたモジュール
+      modules: {
+        // 親モジュールから名前空間を継承する
+        myPage: {
+          state: () => ({ ... }),
+          getters: {
+            profile () { ... } // -> getters['account/profile']
+          }
+        },
+
+        // さらに名前空間をネストする
+        posts: {
+          namespaced: true,
+
+          state: () => ({ ... }),
+          getters: {
+            popular () { ... } // -> getters['account/posts/popular']
+          }
+        }
+      }
+    }
+  }
+})
+```
+
+名前空間のゲッターとアクションは、ローカライズされた `getters`、`dispatch`、`commit` を受け取ります。言い換えれば、同じモジュールに接頭辞 (prefix) を書き込まずに、モジュールアセットを使用することができます。名前空間オプションの切り替えは、モジュール内のコードには影響しません。
+
+### 名前空間付きモジュールでのグローバルアセットへのアクセス
+
+グローバルステートとゲッターを使いたい場合、`rootState` と `rootGetters` はゲッター関数の第3引数と第4引数として渡され、アクション関数に渡される `context` オブジェクトのプロパティとしても公開されます。
+
+アクションをディスパッチするか、グローバル名前空間にミューテーションをコミットするには、`dispatch` と `commit` の3番目の引数として `{root: true}` を渡します。
+
+```js
+modules: {
+  foo: {
+    namespaced: true,
+
+    getters: {
+      // `getters` はこのモジュールのゲッターにローカライズされています
+      // ゲッターの第4引数経由で rootGetters を使うことができます
+      someGetter (state, getters, rootState, rootGetters) {
+        getters.someOtherGetter // -> 'foo/someOtherGetter'
+        rootGetters.someOtherGetter // -> 'someOtherGetter'
+        rootGetters['bar/someOtherGetter'] // -> 'bar/someOtherGetter'
+      },
+      someOtherGetter: state => { ... }
+    },
+
+    actions: {
+      // ディスパッチとコミットもこのモジュール用にローカライズされています
+      // ルートディスパッチ/コミットの `root` オプションを受け入れます
+      someAction ({ dispatch, commit, getters, rootGetters }) {
+        getters.someGetter // -> 'foo/someGetter'
+        rootGetters.someGetter // -> 'someGetter'
+        rootGetters['bar/someGetter'] // -> 'bar/someGetter'
+
+        dispatch('someOtherAction') // -> 'foo/someOtherAction'
+        dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'
+
+        commit('someMutation') // -> 'foo/someMutation'
+        commit('someMutation', null, { root: true }) // -> 'someMutation'
+      },
+      someOtherAction (ctx, payload) { ... }
+    }
+  }
+}
+```
+
+### 名前空間付きモジュールでのグローバルアクションへの登録
+
+名前空間付きモジュールでグローバルアクションに登録したい場合、`root: true` でそれをマークでき、そしてアクション定義を `handler` 関数に置くことができます。例えば:
+
+```js
+{
+  actions: {
+    someOtherAction ({dispatch}) {
+      dispatch('someAction')
+    }
+  },
+  modules: {
+    foo: {
+      namespaced: true,
+
+      actions: {
+        someAction: {
+          root: true,
+          handler (namespacedContext, payload) { ... } // -> 'someAction'
+        }
+      }
+    }
+  }
+}
+```
+
+### 名前空間によるバインディングヘルパー
+
+`mapState`、`mapGetters`、`mapActions`、そして `mapMutations` ヘルパーを使って名前空間付きモジュールをコンポーネントにバインディングするとき、少し冗長になります:
+
+```js
+computed: {
+  ...mapState({
+    a: state => state.some.nested.module.a,
+    b: state => state.some.nested.module.b
+  }),
+  ...mapGetters([
+    'some/nested/module/someGetter', // -> this['some/nested/module/someGetter']
+    'some/nested/module/someOtherGetter', // -> this['some/nested/module/someOtherGetter']
+  ])
+},
+methods: {
+  ...mapActions([
+    'some/nested/module/foo', // -> this['some/nested/module/foo']()
+    'some/nested/module/bar' // -> this['some/nested/module/bar']()
+  ])
+}
+```
+
+このような場合は、第1引数としてモジュールの名前空間文字列をヘルパーに渡すことで、そのモジュールをコンテキストとして使用してすべてのバインディングを行うことができます。上記は次のように単純化できます。
+
+```js
+computed: {
+  ...mapState('some/nested/module', {
+    a: state => state.a,
+    b: state => state.b
+  }),
+  ...mapGetters('some/nested/module', [
+    'someGetter', // -> this.someGetter
+    'someOtherGetter', // -> this.someOtherGetter
+  ])
+},
+methods: {
+  ...mapActions('some/nested/module', [
+    'foo', // -> this.foo()
+    'bar' // -> this.bar()
+  ])
+}
+```
+
+さらに、`createNamespacedHelpers` を使用することによって名前空間付けされたヘルパーを作成できます。指定された名前空間の値にバインドされた新しいコンポーネントバインディングヘルパーを持つオブジェクトを返します:
+
+```js
+import { createNamespacedHelpers } from 'vuex'
+
+const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
+
+export default {
+  computed: {
+    // `some/nested/module` を調べます
+    ...mapState({
+      a: state => state.a,
+      b: state => state.b
+    })
+  },
+  methods: {
+    // `some/nested/module` を調べます
+    ...mapActions([
+      'foo',
+      'bar'
+    ])
+  }
+}
+```
+
+### プラグイン開発者向けの注意事項
+
+モジュールを提供する[プラグイン](plugins.md)を作成し、ユーザーがそれらを Vuex ストアに追加できるようにすると、モジュールの予測できない名前空間が気になるかもしれません。あなたのモジュールは、プラグインユーザーが名前空間付きモジュールの元にモジュールを追加すると、その名前空間に属するようになります。この状況に適応するには、プラグインオプションを使用して名前空間の値を受け取る必要があります。
+
+```js
+// プラグインオプションで名前空間値を取得し、
+// そして、Vuex プラグイン関数を返す
+export function createPlugin (options = {}) {
+  return function (store) {
+    // 名前空間をプラグインモジュールの型に追加する
+    const namespace = options.namespace || ''
+    store.dispatch(namespace + 'pluginAction')
+  }
+}
+```
+
+## 動的にモジュールを登録する
+
+ストアが作られた**後**に `store.registerModule` メソッドを使って、モジュールを登録できます:
+
+```js
+import { createStore } from 'vuex'
+
+const store = createStore({ /* options */ })
+
+// `myModule` モジュールを登録します
+store.registerModule('myModule', {
+  // ...
+})
+
+// ネストされた `nested/myModule` モジュールを登録します
+store.registerModule(['nested', 'myModule'], {
+  // ...
+})
+```
+
+モジュールのステートには `store.state.myModule` と `store.state.nested.myModule` でアクセスします。
+
+動的なモジュール登録があることで、他の Vue プラグインが、モジュールをアプリケーションのストアに付属させることで、状態の管理に Vuex を活用できます。例えば [`vuex-router-sync`](https://github.com/vuejs/vuex-router-sync) ライブラリは、動的に付属させたモジュール内部でアプリケーションのルーティングのステートを管理することで vue-router と vuex を統合しています。
+
+`store.unregisterModule(moduleName)` を呼び出せば、動的に登録したモジュールを削除できます。ただしストア作成(store creation)の際に宣言された、静的なモジュールはこのメソッドで削除できないことに注意してください。
+
+また、すでにモジュールが登録されているかどうかを `store.hasModule(moduleName)` メソッドを使って確認することができます。 One thing to keep in mind is that nested modules should be passed as arrays for both the `registerModule` and `hasModule` and not as a string with the path to the module.
+留意すべき点は、入れ子になっているモジュールは、`registerModule` と `hasModule` の両方に、モジュールへのパスを文字列として渡すのではなく、配列として渡す必要があるということです。
+
+### ステートの保持
+
+サーバサイドレンダリングされたアプリケーションから状態を保持するなど、新しいモジュールを登録するときに、以前の状態を保持したい場合があります。`preserveState` オプション(`store.registerModule('a', module, { preserveState: true })`)でこれを実現できます。
+
+`preserveState: true` を設定した場合、モジュールを登録する際に、アクション、ミューテーション、そしてゲッターは追加されますがステートは追加されません。これはストアのステートはすでにモジュールのステートを登録しているので、それを上書きしないようにするためです。
+
+## モジュールの再利用
+
+時どき、モジュールの複数インスタンスを作成する必要があるかもしれません。例えば:
+
+- 同じモジュールを使用する複数のストアを作成する(例: `runInNewContext` オプションが `false` または `'once'` のとき、[SSR でステートフルなシングルトンを避けるためです](https://ssr.vuejs.org/ja/structure.html#ステートフルなシングルトンの回避)。)
+- 同じストアに同じモジュールを複数回登録する
+
+モジュールの状態を宣言するために単純なオブジェクトを使用すると、その状態オブジェクトは参照によって共有され、変更時にクロスストア/モジュールの状態汚染を引き起こします。
+
+これは、実際には Vue コンポーネント内部の `data` と全く同じ問題です。従って解決策も同じです。モジュールの状態を宣言するために関数を使用してください (2.3.0 以降でサポートされます):
+
+```js
+const MyReusableModule = {
+  state: () => ({
+    foo: 'bar'
+  }),
+  // ミューテーション、アクション、ゲッター...
+}
+```

+ 157 - 0
docs/ja/guide/mutations.md

@@ -0,0 +1,157 @@
+# ミューテーション
+
+<div class="scrimba"><a href="https://scrimba.com/p/pnyzgAP/ckMZp4HN" target="_blank" rel="noopener noreferrer">Scrimba のレッスンを試す</a></div>
+
+実際に Vuex のストアの状態を変更できる唯一の方法は、ミューテーションをコミットすることです。Vuex のミューテーションはイベントにとても近い概念です: 各ミューテーションは**タイプ**と**ハンドラ**を持ちます。ハンドラ関数は Vuex の状態(state)を第1引数として取得し、実際に状態の変更を行います:
+
+```js
+const store = createStore({
+  state: {
+    count: 1
+  },
+  mutations: {
+    increment (state) {
+      // 状態を変更する
+      state.count++
+    }
+  }
+})
+```
+
+直接ミューテーションハンドラを呼び出すことはできません。この mutations オプションは、どちらかいうと "タイプが `increment` のミューテーションがトリガーされたときに、このハンドラが呼ばれる" といったイベント登録のようなものです。ミューテーションハンドラを起動するためにはミューテーションのタイプを指定して `store.commit` を呼び出す必要があります:
+
+```js
+store.commit('increment')
+```
+
+## 追加の引数を渡してコミットする
+
+`store.commit` に追加の引数を渡すこともできます。この追加の引数は、特定のミューテーションに対する**ペイロード**と呼びます:
+
+```js
+// ...
+mutations: {
+  increment (state, n) {
+    state.count += n
+  }
+}
+```
+
+```js
+store.commit('increment', 10)
+```
+
+ほとんどの場合、ペイロードはオブジェクトにすべきです。そうすることで複数のフィールドを含められるようになり、またミューテーションがより記述的に記録されるようになります:
+
+```js
+// ...
+mutations: {
+  increment (state, payload) {
+    state.count += payload.amount
+  }
+}
+```
+
+```js
+store.commit('increment', {
+  amount: 10
+})
+```
+
+## オブジェクトスタイルのコミット
+
+また `type` プロパティを持つオブジェクトを使って、ミューテーションをコミットすることもできます:
+
+```js
+store.commit({
+  type: 'increment',
+  amount: 10
+})
+```
+
+オブジェクトスタイルでコミットするとき、オブジェクト全体がペイロードとしてミューテーションハンドラに渡されます。したがってハンドラの例は上記と同じです:
+
+```js
+mutations: {
+  increment (state, payload) {
+    state.count += payload.amount
+  }
+}
+```
+
+## ミューテーション・タイプに定数を使用する
+
+いろいろな Flux 実装において、ミューテーション・タイプに定数を使用することが共通して見られるパターンです。これはコードに対してリントツールのようなツールを利用できるという利点があり、また単一ファイルに全ての定数を設定することによって、共同で作業する人に、アプリケーション全体で何のミューテーションが可能であるかを一目見ただけで理解できるようにします:
+
+```js
+// mutation-types.js
+export const SOME_MUTATION = 'SOME_MUTATION'
+```
+
+```js
+// store.js
+import { createStore } from 'vuex'
+import { SOME_MUTATION } from './mutation-types'
+
+const store = createStore({
+  state: { ... },
+  mutations: {
+    // 定数を関数名として使用できる ES2015 の算出プロパティ名(computed property name)機能を使用できます
+    [SOME_MUTATION] (state) {
+      // 状態を変更する
+    }
+  }
+})
+```
+
+定数を使用するかどうかは好みの問題です。多くの開発者による大規模なプロジェクトで役に立ちますが、完全にオプションなので、もしお気に召さなければ使用しなくても構いません。
+
+## ミューテーションは同期的でなければならない
+
+ひとつの重要なルールを覚えておきましょう。それは**ミューテーションハンドラ関数は同期的でなければならない**ということです。なぜか?次の例で考えてみましょう:
+
+```js
+mutations: {
+  someMutation (state) {
+    api.callAsyncMethod(() => {
+      state.count++
+    })
+  }
+}
+```
+
+いま、開発ツールのミューテーションのログを見ながら、アプリケーションのデバッグを行っていることを想像してください。全てのミューテーションをログに記録するためには、ミューテーションの前後の状態のスナップショットを捕捉することが必要です。しかし、上の例にあるミューテーション内の非同期コールバックは、それを不可能にします: そのコールバックは、ミューテーションがコミットされた時点ではまだ呼び出されていません。そして、コールバックが実際にいつ呼び出されるかを、開発ツールは知る術がありません。いかなる状態変更でも、コールバック内で起きる場合は本質的に追跡不可能です。
+
+## コンポーネント内におけるミューテーションのコミット
+
+`this.$store.commit('xxx')` と書くか、もしくはコンポーネントのメソッドを `store.commit` にマッピングする `mapMutations` ヘルパーを呼び出すこと(ルートの `store` の注入が必要)で、コンポーネント内でミューテーションをコミットできます:
+
+```js
+import { mapMutations } from 'vuex'
+
+export default {
+  // ...
+  methods: {
+    ...mapMutations([
+      'increment', // `this.increment()` を `this.$store.commit('increment')` にマッピングする
+
+      // mapMutations はペイロードサポートする:
+      'incrementBy' // `this.incrementBy(amount)` を `this.$store.commit('incrementBy', amount)` にマッピングする
+    ]),
+    ...mapMutations({
+      add: 'increment' // `this.add()` を `this.$store.commit('increment')` にマッピングする
+    })
+  }
+}
+```
+
+## アクションへ向けて
+
+状態変更を非同期に組み合わせることは、プログラムの動きを予測することを非常に困難にします。例えば、状態を変更する非同期コールバックを持った 2つのメソッドを両方呼び出すとき、それらがいつ呼び出されたか、どちらが先に呼び出されたかを、どうやって知ればよいのでしょう?これがまさに、状態変更と非同期の 2つの概念を分離したいという理由です。Vuex では**全てのミューテーションは同期的に行う**という作法になっています:
+
+```js
+store.commit('increment')
+// "increment" ミューテーションによる状態変更は、この時点で行われるべきです
+```
+
+非同期的な命令を扱うために[アクション](actions.md)を見てみましょう。

+ 137 - 0
docs/ja/guide/plugins.md

@@ -0,0 +1,137 @@
+# プラグイン 
+
+<div class="scrimba"><a href="https://scrimba.com/p/pnyzgAP/cvp8ZkCR" target="_blank" rel="noopener noreferrer">Scrimba のレッスンを試す</a></div>
+
+Vuex ストア は、各ミューテーションへのフックを公開する `plugins` オプションを受け付けます。 Vuex プラグインは、単一の引数としてストアを受けつけるただの関数です:
+
+```js
+const myPlugin = (store) => {
+  // ストアが初期化されたときに呼ばれます
+  store.subscribe((mutation, state) => {
+    // それぞれのミューテーションの後に呼ばれます
+    // ミューテーションは `{ type, payload }` の形式で提供されます
+  })
+}
+```
+
+そして、このように利用することができます:
+
+```js
+const store = createStore({
+  // ...
+  plugins: [myPlugin]
+})
+```
+
+## プラグイン内でのミューテーションのコミット
+
+プラグインは直接、状態を変更できません。これはコンポーネントに似ています。プラグインはコンポーネント同様に、ミューテーションのコミットをトリガーすることで状態を変更できます。
+
+ミューテーションのコミットによるストアとデータソースの同期をプラグインで実現できます。 websocket データソースとストアを例にします (これは不自然で作為的な例です。実際には `createWebSocketPlugin` 関数は、さらに複雑なタスクのために追加でいくつかのオプションを受け取れます):
+
+```js
+export default function createWebSocketPlugin (socket) {
+  return (store) => {
+    socket.on('data', data => {
+      store.commit('receiveData', data)
+    })
+    store.subscribe(mutation => {
+      if (mutation.type === 'UPDATE_DATA') {
+        socket.emit('update', mutation.payload)
+      }
+    })
+  }
+}
+```
+
+```js
+const plugin = createWebSocketPlugin(socket)
+
+const store = createStore({
+  state,
+  mutations,
+  plugins: [plugin]
+})
+```
+
+## 状態のスナップショットを撮る
+
+時々、状態の"スナップショット"を撮って、ミューテーション前後の状態を比較したくなることがあるでしょう。それを実現するために、状態オブジェクトのディープコピーを行う必要があります:
+
+```js
+const myPluginWithSnapshot = (store) => {
+  let prevState = _.cloneDeep(store.state)
+  store.subscribe((mutation, state) => {
+    let nextState = _.cloneDeep(state)
+
+    // `prevState` と `nextState` を比較...
+
+    // 次のミューテーションのために状態を保存
+    prevState = nextState
+  })
+}
+```
+
+**状態のスナップショットを撮るプラグインはアプリケーションの開発の間だけ使われるべきです。**  webpack や Browserify を使っていれば、ビルドツールにそれを処理させることができます:
+
+```js
+const store = createStore({
+  // ...
+  plugins: process.env.NODE_ENV !== 'production'
+    ? [myPluginWithSnapshot]
+    : []
+})
+```
+
+上のように記述すれば、プラグインはデフォルトで利用されることになります。本番環境( production ) では、 `process.env.NODE_ENV !== 'production'` を `false` に置き換えるために、 webpack では[DefinePlugin](https://webpack.js.org/plugins/define-plugin/) 、 Browserify では[envify](https://github.com/hughsk/envify) が必要になります。
+
+## ビルトインロガープラグイン
+
+Vuex には、一般的なデバッグに利用する用途の備え付けのロガープラグインがあります。
+
+```js
+import { createLogger } from 'vuex'
+
+const store = createStore({
+  plugins: [createLogger()]
+})
+```
+
+`createLogger` 関数はいくつかのオプションを受け取ります:
+
+```js
+const logger = createLogger({
+  collapsed: false, // ログ出力されたミューテーションを自動で展開します
+  filter (mutation, stateBefore, stateAfter) {
+    // ミューテーションを記録する必要がある場合は、`true` を返します
+    // `mutation` は `{ type, payload }` です
+    return mutation.type !== "aBlocklistedMutation"
+  },
+  actionFilter (action, state) {
+    // `filter` と同等ですが、アクション用です
+    // `action` は `{ type, payloed }` です
+    return action.type !== "aBlocklistedAction"
+  },
+  transformer (state) {
+    // ロギングの前に、状態を変換します
+    // 例えば、特定のサブツリーのみを返します
+    return state.subTree
+  },
+  mutationTransformer (mutation) {
+    // ミューテーションは、`{ type, payload }` の形式でログ出力されます
+    // 任意の方法でそれをフォーマットできます
+    return mutation.type
+  },
+  actionTransformer (action) {
+    // `mutationTransformer` と同等ですが、アクション用です
+    return action.type
+  },
+  logActions: true, // アクションログを出力します。
+  logMutations: true, // ミューテーションログを出力します。
+  logger: console, // `console` API の実装, デフォルトは `console`
+})
+```
+
+ロガーファイルは、他にも `<script>` タグで直接読み込むことができ、`createVuexLogger` 関数がグローバルに公開されます。
+
+ロガープラグインは、状態のスナップショットを撮ることに注意しましょう。スナップショットを撮ることはコストがかかるため、開発中だけ利用してください。

+ 98 - 0
docs/ja/guide/state.md

@@ -0,0 +1,98 @@
+# ステート
+
+## 単一ステートツリー
+
+<div class="scrimba"><a href="https://scrimba.com/p/pnyzgAP/cWw3Zhb" target="_blank" rel="noopener noreferrer">Scrimba のレッスンを試す</a></div>
+
+Vuex は **単一ステートツリー (single state tree)** を使います。つまり、この単一なオブジェクトはアプリケーションレベルの状態が全て含まれており、"信頼できる唯一の情報源 (single source of truth)" として機能します。これは、通常、アプリケーションごとに1つしかストアは持たないことを意味します。単一ステートツリーは状態の特定の部分を見つけること、デバッグのために現在のアプリケーションの状態のスナップショットを撮ることを容易にします。
+
+単一ステートツリーはモジュール性と競合しません。以降の章で、アプリケーションの状態とミューテーション(変更)をサブモジュールに分割する方法について説明します。
+
+Vuexに保存するデータは、Vueインスタンスの `data` と同じルールに従います。つまり、ステートオブジェクトはプレーンでなければなりません。[Vue#data](https://v3.ja.vuejs.org/api/options-data.html#data-2)も参照してください。
+
+## Vuex の状態を Vue コンポーネントに入れる
+
+ストアにある状態を Vue コンポーネント に表示するにはどうすればよいのでしょう? Vuex ストア はリアクティブなので、ストアから状態を"取り出す"一番シンプルな方法は、単純にいくつかのストアの状態を [算出プロパティ](https://jp.vuejs.org/guide/computed.html) で返すことです。
+
+```js
+// Counter コンポーネントをつくってみましょう
+const Counter = {
+  template: `<div>{{ count }}</div>`,
+  computed: {
+    count () {
+      return store.state.count
+    }
+  }
+}
+```
+
+`store.state.count` が変わるたび、算出プロパティの再評価が発生し、関連した DOM の更新をトリガーします。
+
+しかし、このパターンでは、コンポーネントがグローバルストアシングルトンに依存してしまいます。 モジュールシステムを使っているとき、ストアの状態を使っているすべてのコンポーネントでインポートが必要です。また、コンポーネントのテストのときにモック化が必要となります。
+
+Vuex は Vue のプラグインシステムを通じて、ルートコンポーネントからすべての子コンポーネントにストアを "注入" し、それらのコンポーネントでは `this.$store` として利用できるようになります。それでは `Counter` の実装を変更しましょう:
+
+```js
+const Counter = {
+  template: `<div>{{ count }}</div>`,
+  computed: {
+    count () {
+      return this.$store.state.count
+    }
+  }
+}
+```
+
+## `mapState` ヘルパー
+
+<div class="scrimba"><a href="https://scrimba.com/p/pnyzgAP/c8Pz7BSK" target="_blank" rel="noopener noreferrer">Scrimba のレッスンを試す</a></div>
+
+コンポーネントが複数のストアのステートプロパティやゲッターを必要としているとき、これらすべてにおいて、算出プロパティを宣言することは繰り返しで冗長です。これに対処するため、算出ゲッター関数を生成し、いくつかのキーストロークを省くのに役立つ `mapState` ヘルパーを使うことができます:
+
+```js
+// 完全ビルドでは、ヘルパーは Vuex.mapState として公開されています
+import { mapState } from 'vuex'
+
+export default {
+  // ...
+  computed: mapState({
+    // アロー関数は、コードをとても簡潔にできます!
+    count: state => state.count,
+
+    // 文字列を渡すことは、`state => state.count` と同じです
+    countAlias: 'count',
+
+    // `this` からローカルステートを参照するときは、通常の関数を使わなければいけません
+    countPlusLocalState (state) {
+      return state.count + this.localCount
+    }
+  })
+}
+```
+
+マップされた算出プロパティの名前がステートサブツリーの名前と同じ場合は、文字列配列を `mapState` に渡すこともできます。
+
+```js
+computed: mapState([
+  // map this.count to store.state.count
+  'count'
+])
+```
+
+## オブジェクトスプレッド演算子
+
+`mapState` はオブジェクトを返すことに注意しましょう。どうやって、他のローカル算出プロパティと組み合わせるのでしょうか? 通常、最終的にひとつのオブジェクトを `computed` に渡せるように、複数のオブジェクトをひとつにマージするユーティリティを使わなければいけません。しかし、[オブジェクトスプレッド演算子](https://github.com/tc39/proposal-object-rest-spread)で、シンタックスをかなり単純にできます:
+
+```js
+computed: {
+  localComputed () { /* ... */ },
+  // オブジェクトスプレット演算子で、外のオブジェクトとこのオブジェクトを混ぜる
+  ...mapState({
+    // ...
+  })
+}
+```
+
+## コンポーネントはまだローカルステートを持つことできる
+
+Vuex を使うということは、**全て**の状態を Vuex の中に置くべき、というわけではありません。多くの状態を Vuex に置くことで、状態の変更がさらに明示的、デバッグ可能になりますが、ときにはコードを冗長でまわりくどいものにします。状態の一部がひとつのコンポーネントだけに属している場合は、それをローカルの状態として残しておくとよいでしょう。あなたは、トレードオフを考慮した上で、あなたのアプリの開発ニーズに合った決定をすべきです。

+ 25 - 0
docs/ja/guide/strict.md

@@ -0,0 +1,25 @@
+# 厳格モード
+
+厳格(strict)モードを有効にするには Vuex store を作成するときに、ただ `strict: true` を指定するだけです:
+
+```js
+const store = createStore({
+  // ...
+  strict: true
+})
+```
+
+厳格モードでは Vuex の状態がミューテーションハンドラの外部で変更されたら、エラーを投げるようになります。これで全ての状態変更がデバッギングツールで明示的に追跡できることが保証されます。
+
+## 開発環境 vs 本番環境
+
+**本番環境で厳格モードを有効にしてデプロイしてはいけません!** 厳格モードでは不適切なミューテーションを検出するためにステートツリーに対して深い監視を実行します。パフォーマンスコストを回避するために本番環境では無効にしてください。
+
+プラグインと同様に、ビルドツールに処理させることができます:
+
+```js
+const store = createStore({
+  // ...
+  strict: process.env.NODE_ENV !== 'production'
+})
+```

+ 32 - 0
docs/ja/guide/structure.md

@@ -0,0 +1,32 @@
+# アプリケーションの構造
+
+Vuex は実際のところ、あなたがコードを構造化する方法を制限しません。もっと正確に言うと、それより高いレベルの原理原則を適用させます:
+
+1. アプリケーションレベルの状態はストアに集約されます。
+
+2. 状態を変更する唯一の方法は、同期的に処理を行う**ミューテーション**をコミットすることのみです。
+
+3. 非同期的なロジックはカプセル化されるべきであり、それは**アクション**によって構成されます。
+
+これらのルールに従っている限り、プロジェクトをどのように構造化するかはあなた次第です。もしストアファイルが大きくなり過ぎたら、単純にアクションやミューテーション、ゲッターをそれぞれ別のファイルに切り出すことができます。
+
+それなりに手の込んだアプリケーションであれば、モジュールを活用する必要が出てきそうです。プロジェクトの構造の例は以下のようになります:
+
+```bash
+├── index.html
+├── main.js
+├── api
+│   └── ... # API 呼び出しを抽象化する
+├── components
+│   ├── App.vue
+│   └── ...
+└── store
+    ├── index.js          # モジュールを集めてストアをエクスポートする
+    ├── actions.js        # アクションのルートファイル
+    ├── mutations.js      # ミューテーションのルートファイル
+    └── modules
+        ├── cart.js       # cart モジュール
+        └── products.js   # products モジュール
+```
+
+参考として [Shopping Cart Example](https://github.com/vuejs/vuex/tree/4.0/examples/classic/shopping-cart) をみてみるのもよいでしょう。

+ 239 - 0
docs/ja/guide/testing.md

@@ -0,0 +1,239 @@
+# テスト
+
+<div class="scrimba"><a href="https://scrimba.com/p/pnyzgAP/cPGkpJhq" target="_blank" rel="noopener noreferrer">Scrimba のレッスンを試す</a></div>
+
+私たちが Vuex でユニットテストしたい主な部分はミューテーションとアクションです。
+
+## ミューテーションのテスト
+
+ミューテーションは完全に引数に依存しているだけの関数であるため、テストするのがとても簡単です。効果的なやり方として、もし ES2015 のモジュールを使っていて `store.js` ファイルの中にミューテーションがあるなら、デフォルトエクスポートに加えて、名前付きエクスポートでミューテーションをエクスポートできます。
+
+```js
+const state = { ... }
+
+// 名前付きエクスポートでミューテーションをエクスポートする
+export const mutations = { ... }
+
+export default createStore({
+  state,
+  mutations
+})
+```
+
+Mocha + Chai を使用してミューテーションをテストする例です(あなたの好きな任意のフレームワーク/アサーションライブラリを使用できます):
+
+```js
+// mutations.js
+export const mutations = {
+  increment: state => state.count++
+}
+```
+
+```js
+// mutations.spec.js
+import { expect } from 'chai'
+import { mutations } from './store'
+
+// ミューテーションの分割束縛
+const { increment } = mutations
+
+describe('mutations', () => {
+  it('INCREMENT', () => {
+    // ステートのモック
+    const state = { count: 0 }
+    // ミューテーションを適用する
+    increment(state)
+    // 結果を検証する
+    expect(state.count).to.equal(1)
+  })
+})
+```
+
+## アクションのテスト
+
+アクションは外部の API を呼び出す可能性があるため、ミューテーションのテストよりも少し注意が必要です。アクションをテストするとき、通常、いくつかの段階でモックを作る必要があります。例えば API 呼び出しをサービスとして抽象化し、そしてテストの内部ではそのサービスをモックにすることができます。簡単に依存関係をモック化するために、webpack と [inject-loader](https://github.com/plasticine/inject-loader) を使ってテストファイルをバンドルすることができます。
+
+非同期なアクションのテストの例:
+
+```js
+// actions.js
+import shop from '../api/shop'
+
+export const getAllProducts = ({ commit }) => {
+  commit('REQUEST_PRODUCTS')
+  shop.getProducts(products => {
+    commit('RECEIVE_PRODUCTS', products)
+  })
+}
+```
+
+```js
+// actions.spec.js
+
+// inline loader のために require 構文を使用する
+// ここでは inject-loader を使って、モック化された依存関係を注入できるようにするモジュールファクトリーを返す
+import { expect } from 'chai'
+const actionsInjector = require('inject-loader!./actions')
+
+// モックによってモジュールを作成する
+const actions = actionsInjector({
+  '../api/shop': {
+    getProducts (cb) {
+      setTimeout(() => {
+        cb([ /* レスポンスのモック */ ])
+      }, 100)
+    }
+  }
+})
+
+// 期待されるミューテーションをアクションが呼び出すかをテストするためのヘルパー
+const testAction = (action, payload, state, expectedMutations, done) => {
+  let count = 0
+
+  // コミットをモックする
+  const commit = (type, payload) => {
+    const mutation = expectedMutations[count]
+
+    try {
+      expect(type).to.equal(mutation.type)
+      expect(payload).to.deep.equal(mutation.payload)
+    } catch (error) {
+      done(error)
+    }
+
+    count++
+    if (count >= expectedMutations.length) {
+      done()
+    }
+  }
+
+  // モック化したストアと引数でアクションを呼び出す
+  action({ commit, state }, payload)
+
+  // 呼び出されるべきミューテーションが残っていないか確認する
+  if (expectedMutations.length === 0) {
+    expect(count).to.equal(0)
+    done()
+  }
+}
+
+describe('actions', () => {
+  it('getAllProducts', done => {
+    testAction(actions.getAllProducts, null, {}, [
+      { type: 'REQUEST_PRODUCTS' },
+      { type: 'RECEIVE_PRODUCTS', payload: { /* レスポンスのモック */ } }
+    ], done)
+  })
+})
+```
+
+テスト環境において利用可能なスパイがあるのなら(例えば[Sinon.JS](http://sinonjs.org/))、`testAction` ヘルパーの代わりにそれらを使用できます:
+
+```js
+describe('actions', () => {
+  it('getAllProducts', () => {
+    const commit = sinon.spy()
+    const state = {}
+
+    actions.getAllProducts({ commit, state })
+
+    expect(commit.args).to.deep.equal([
+      ['REQUEST_PRODUCTS'],
+      ['RECEIVE_PRODUCTS', { /* レスポンスのモック */ }]
+    ])
+  })
+})
+```
+
+## ゲッターのテスト
+
+もしゲッターが複雑な計算を行っているならば、テストコードを書く価値があります。ゲッターはミューテーションと同様の理由でテストしやすいです。
+
+ゲッターのテストの例:
+
+```js
+// getters.js
+export const getters = {
+  filteredProducts (state, { filterCategory }) {
+    return state.products.filter(product => {
+      return product.category === filterCategory
+    })
+  }
+}
+```
+
+```js
+// getters.spec.js
+import { expect } from 'chai'
+import { getters } from './getters'
+
+describe('getters', () => {
+  it('filteredProducts', () => {
+    // ステートをモックする
+    const state = {
+      products: [
+        { id: 1, title: 'Apple', category: 'fruit' },
+        { id: 2, title: 'Orange', category: 'fruit' },
+        { id: 3, title: 'Carrot', category: 'vegetable' }
+      ]
+    }
+    // ゲッターをモックする
+    const filterCategory = 'fruit'
+
+    // ゲッターから結果を受け取る
+    const result = getters.filteredProducts(state, { filterCategory })
+
+    // 結果を検証する
+    expect(result).to.deep.equal([
+      { id: 1, title: 'Apple', category: 'fruit' },
+      { id: 2, title: 'Orange', category: 'fruit' }
+    ])
+  })
+})
+```
+
+## テストの実行
+
+ミューテーションやアクションが適切に書かれている場合は、適切にモック化された後、テストコードはブラウザの API に直接依存関係を持つことはないでしょう。したがって、単純に webpack でテストをバンドルでき、それを直接 Node で実行できます。別の方法として、本当のブラウザでテストを実行するためには `mocha-loader` または Karma + `karma-webpack` を使用できます。
+
+### Node での実行
+
+以下のような webpack の設定を作成します([`.babelrc`](https://babeljs.io/docs/usage/babelrc/) もあわせて使います):
+
+```js
+// webpack.config.js
+module.exports = {
+  entry: './test.js',
+  output: {
+    path: __dirname,
+    filename: 'test-bundle.js'
+  },
+  module: {
+    loaders: [
+      {
+        test: /\.js$/,
+        loader: 'babel-loader',
+        exclude: /node_modules/
+      }
+    ]
+  }
+}
+```
+
+それから下記コマンドを実行します:
+
+``` bash
+webpack
+mocha test-bundle.js
+```
+
+### ブラウザでの実行
+
+1. `mocha-loader` をインストールする
+2. 上記 webpack 設定から `entry` を `'mocha-loader!babel-loader!./test.js'` に変更する
+3. 設定を使用して `webpack-dev-server` を開始する
+4. ブラウザで `localhost:8080/webpack-dev-server/test-bundle` を開く
+
+### Karma + karma-webpack を使ったブラウザでの実行
+
+[vue-loader ドキュメント](https://vue-loader.vuejs.org/ja/workflow/testing.html) 内のセットアップ方法を参考にしてください。

+ 134 - 0
docs/ja/guide/typescript-support.md

@@ -0,0 +1,134 @@
+# TypeScript サポート
+
+Vuex は型付けを提供しているので、TypeScript を使ってストア定義を書くことができます。Vuex には特別な TypeScript の設定は必要ありません。[Vue の基本的な TypeScript の設定](https://v3.ja.vuejs.org/guide/typescript-support.html) に従ってプロジェクトの設定を行ってください。
+
+しかし、Vue コンポーネントを TypeScript で書いている場合は、ストアの型付けを正しく行うために必要な手順がいくつかあります。
+
+## Vue コンポーネントでの `$store` プロパティの型付け
+
+Vuex はすぐに使用できる `this.$store` プロパティの型付けを提供していません。TypeScriptと併用する場合は、独自のモジュール拡張を宣言する必要があります。
+
+プロジェクトフォルダに宣言ファイルを追加して、Vue の `ComponentCustomProperties` のカスタム型付けを宣言します。
+
+```ts
+// vuex.d.ts
+import { ComponentCustomProperties } from 'vue'
+import { Store } from 'vuex'
+
+declare module '@vue/runtime-core' {
+  // ストアのステートを宣言する
+  interface State {
+    count: number
+  }
+
+  // `this.$store` の型付けを提供する
+  interface ComponentCustomProperties {
+    $store: Store<State>
+  }
+}
+```
+
+## `useStore` 関数の型付け
+
+Composition API で Vue コンポーネントを記述する際には、ほとんどの場合、`useStore`が型付けされたストアを返すようにしたいでしょう。`useStore` が正しく型付けされたストアを返すためには次のことが必要です。
+
+1. 型付けされた `InjectionKey` を定義する。
+2. ストアをインストールする際に、型付けされた `InjectionKey` を Vue App インスタンスに渡す。
+3. 型付けされた `InjectionKey` を `useStore` メソッドに渡す。
+
+それでは、順を追って説明していきます。まずは、Vue の `InjectionKey` インターフェースを使って独自のストアの型定義とともにキーを定義します。
+
+```ts
+// store.ts
+import { InjectionKey } from 'vue'
+import { createStore, Store } from 'vuex'
+
+// ストアのステートに対して型を定義します
+export interface State {
+  count: number
+}
+
+// インジェクションキーを定義します
+export const key: InjectionKey<Store<State>> = Symbol()
+
+export const store = createStore<State>({
+  state: {
+    count: 0
+  }
+})
+```
+
+次に、ストアのインストール時に定義した `InjectionKey` を Vue App インスタンスに渡します。
+
+```ts
+// main.ts
+import { createApp } from 'vue'
+import { store, key } from './store'
+
+const app = createApp({ ... })
+
+// pass the injection key
+app.use(store, key)
+
+app.mount('#app')
+```
+
+最後に、このキーを `useStore` メソッドに渡すことで型付けされたストアを取得することができます。
+
+```ts
+// in a vue component
+import { useStore } from 'vuex'
+import { key } from './store'
+
+export default {
+  setup () {
+    const store = useStore(key)
+
+    store.state.count // typed as number
+  }
+}
+```
+
+内部的には、Vuex は Vue の [Provide/Inject](https://v3.ja.vuejs.org/api/composition-api.html#provide-inject) 機能を使って Vue App インスタンスにストアをインストールします。これが、 `InjectionKey` によって型定義を提供できる理由です。
+
+### `useStore` 使用方法の簡略化
+
+`useStore` 関数を使うたびに `InjectionKey` をインポートして、 `useStore` へ渡さなければならないのは少し面倒かもしれません。その場合、型付けされたストアを取得する独自の関数を定義すると良いでしょう。
+
+```ts
+// store.ts
+import { InjectionKey } from 'vue'
+import { createStore, useStore as baseUseStore, Store } from 'vuex'
+
+export interface State {
+  count: number
+}
+
+export const key: InjectionKey<Store<State>> = Symbol()
+
+export const store = createStore<State>({
+  state: {
+    count: 0
+  }
+})
+
+// 独自の `useStore` 関数を定義します
+export function useStore () {
+  return baseUseStore(key)
+}
+```
+
+この関数を使用することで、 `InjectionKey` とその型を提供しなくても、型付けされたストアを取得することができます。
+
+```ts
+// vue component 内
+import { useStore } from './store'
+
+export default {
+  setup () {
+    const store = useStore()
+
+    store.state.count // number として型付け
+  }
+}
+```

+ 73 - 0
docs/ja/index.md

@@ -0,0 +1,73 @@
+# Vuex とは何か?
+
+::: tip 注意
+これは、Vue 3 で動作する Vuex 4 のためのドキュメントです。Vue 2 で動作する Vuex 3 のドキュメントをお探しの方は、[こちらをご覧ください](https://vuex.vuejs.org/ja/)。
+:::
+
+Vuex は Vue.js アプリケーションのための **状態管理パターン + ライブラリ**です。
+これは予測可能な方法によってのみ状態の変異を行うというルールを保証し、アプリケーション内の全てのコンポーネントのための集中型のストアとして機能します。
+
+## "状態管理パターン"とはなんですか?
+
+単純な Vue で作られたカウンターアプリをみてみましょう:
+
+```js
+const Counter = {
+  // state
+  data () {
+    return {
+      count: 0
+    }
+  },
+  // view
+  template: `
+    <div>{{ count }}</div>
+  `,
+  // actions
+  methods: {
+    increment () {
+      this.count++
+    }
+  }
+}
+
+createApp(Counter).mount('#app')
+```
+
+これはいくつかの要素をアプリ自身に含んでいます:
+
+- **状態**、これは私達のアプリを動かす信頼できる情報源(the source of truth)です。
+- **ビュー**、これは**状態**のただの宣言的なマッピングです。
+- **アクション**、これは**ビュー**からのユーザー入力に反応して、状態の変更を可能にする方法です。
+
+これらは"単方向データフロー"のコンセプトの極めてシンプルな責務です:
+
+<p style="text-align: center; margin: 2em">
+  <img style="width:100%; max-width:450px;" src="/flow.png">
+</p>
+
+しかし、単純さは、**共通の状態を共有する複数のコンポーネントを持ったときに**、すぐに破綻します:
+
+- 複数のビューが同じ状態に依存することがあります。
+- 異なるビューからのアクションで、同じ状態を変更する必要があります。
+
+一つ目は、プロパティ (props) として深く入れ子になったコンポーネントに渡すのは面倒で、兄弟コンポーネントでは単純に機能しません。二つ目は、親子のインスタンスを直接参照したり、イベントを介して複数の状態のコピーを変更、同期することを試みるソリューションに頼っていることがよくあります。これらのパターンは、いずれも脆く、すぐにメンテナンスが困難なコードに繋がります。
+
+では、コンポーネントから共有している状態を抽出し、それをグローバルシングルトンで管理するのはどうでしょうか? これにより、コンポーネントツリーは大きな "ビュー" となり、どのコンポーネントもツリー内のどこにあっても状態にアクセスしたり、アクションをトリガーできます!
+
+さらに、状態管理に関わる概念を定義、分離し、特定のルールを敷くことで、コードの構造と保守性を向上させることができます。
+
+これが Vuex の背景にある基本的なアイディアであり、[Flux](https://facebook.github.io/flux/docs/overview)、 [Redux](http://redux.js.org/) そして [The Elm Architecture](https://guide.elm-lang.org/architecture/)から影響を受けています。
+他のパターンと異なるのは、Vuex は効率的な更新のために、Vue.js の粒度の細かいリアクティビティシステムを利用するよう特別に調整して実装されたライブラリだということです。
+
+あなたがもし対話型の方法でVuexを学びたいのであれば、[Scrimba](https://scrimba.com/g/gvuex)のVuexコースをぜひ試してみてください。
+
+![vuex](/vuex.png)
+
+## いつ、Vuexを使うべきでしょうか?
+
+Vuex は、共有状態の管理に役立ちますが、さらに概念やボイラープレートのコストがかかります。これは、短期的生産性と長期的生産性のトレードオフです。
+
+もし、あなたが大規模な SPA を構築することなく、Vuex を導入した場合、冗長で気が遠くなるように感じるかもしれません。そう感じることは全く普通です。あなたのアプリがシンプルであれば、Vuex なしで問題ないでしょう。単純な [ストアパターン](https://v3.ja.vuejs.org/guide/state-management.html#simple-state-management-from-scratch) が必要なだけかもしれません。しかし、今あなたが中規模から大規模の SPA を構築しているなら、Vue コンポーネントの外の状態をもっとうまく扱えないか考えなくてはならない状況にあるかもしれません。その場合 Vuex は次のステップとして最適でしょう。これは Redux の作者、Dan Abramov からの良い引用です:
+
+> Flux ライブラリは眼鏡のようなものです: あなたが必要な時にいつでも分かるのです。

+ 64 - 0
docs/ja/installation.md

@@ -0,0 +1,64 @@
+# インストール
+
+## 直接ダウンロードする / CDN
+
+[https://unpkg.com/vuex@4](https://unpkg.com/vuex@4)
+
+<!--email_off-->
+[Unpkg.com](https://unpkg.com) で NPM ベースの CDN リンクが提供されています。上記リンクは常に NPM の最新のリリースを指します。`https://unpkg.com/vuex@4.0.0/dist/vuex.global.js` のような URL によって特定のバージョン/タグを利用することもできます。
+<!--/email_off-->
+
+Vue のあとで `vuex` を取り込むと自動的に Vuex が導入されます:
+
+```html
+<script src="/path/to/vue.js"></script>
+<script src="/path/to/vuex.js"></script>
+```
+
+## NPM
+
+```bash
+npm install vuex@next --save
+```
+
+## Yarn
+
+```bash
+yarn add vuex@next --save
+```
+
+## Promise
+
+Vuex は [Promise (プロミス)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) を必要とします。ブラウザで Promise が実装されていない(例 IE)場合は、[es6-promise](https://github.com/stefanpenner/es6-promise) のようなポリフィルライブラリを使用できます。
+
+CDN 経由でそれを含めることができます:
+
+```html
+<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>
+```
+
+`window.Promise` は自動的に有効になります。
+
+NPM または Yarn のようなパッケージマネージャーを使用するのを希望する場合は、以下のコマンドでインストールします:
+
+```bash
+npm install es6-promise --save # NPM
+yarn add es6-promise # Yarn
+```
+
+さらに、Vuex を使用する前に、コードのどこかに次の行を追加します:
+
+```js
+import 'es6-promise/auto'
+```
+
+## 開発版ビルド
+
+最新の開発版ビルドを利用したい場合には、 GitHub から直接クローンし `vuex` を自身でビルドする必要があります。
+
+```bash
+git clone https://github.com/vuejs/vuex.git node_modules/vuex
+cd node_modules/vuex
+yarn
+yarn build
+```