+```
+
+Then add a static values definition to the controller and change the initialize() method to log this.indexValue:
+
+```javascript
+export default class extends Controller {
+ static values = { index: Number }
+
+ initialize() {
+ console.log(this.indexValue)
+ console.log(typeof this.indexValue)
+ }
+
+ // …
+}
+```
+
+Reload the page and verify that the console shows 1 and Number.
+
+
+## static valuesの行の意味
+
+ターゲットと同様に、`values`という静的オブジェクトプロパティに値を記述して定義します。 ここでは、`index`という単一の数値を定義しています。 値の定義については、リファレンスを参照してください。
+
+それでは、コントローラの`initialize()`と他のメソッドを修正して、`this.index`の代わりに`this.indexValue`を使用するようにしましょう:
+
+```javascript
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ static targets = [ "slide" ]
+ static values = { index: Number }
+
+ initialize() {
+ this.showCurrentSlide()
+ }
+
+ next() {
+ this.indexValue++
+ this.showCurrentSlide()
+ }
+
+ previous() {
+ this.indexValue--
+ this.showCurrentSlide()
+ }
+
+ showCurrentSlide() {
+ this.slideTargets.forEach((element, index) => {
+ element.hidden = index !== this.indexValue
+ })
+ }
+}
+```
+
+ページをリロードし、Webインスペクタを使って、controller要素の`data-slideshow-index-value`属性が、次のスライドに移るたびに変化することを確認しましょう。
+
+
+
+原文
+
+Similar to targets, you define values in a Stimulus controller by describing them in a static object property called values. In this case, we’ve defined a single numeric value called index. You can read more about value definitions in the reference documentation.
+
+Now let’s update initialize() and the other methods in the controller to use this.indexValue instead of this.index. Here’s how the controller should look when we’re done:
+
+```javascript
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ static targets = [ "slide" ]
+ static values = { index: Number }
+
+ initialize() {
+ this.showCurrentSlide()
+ }
+
+ next() {
+ this.indexValue++
+ this.showCurrentSlide()
+ }
+
+ previous() {
+ this.indexValue--
+ this.showCurrentSlide()
+ }
+
+ showCurrentSlide() {
+ this.slideTargets.forEach((element, index) => {
+ element.hidden = index !== this.indexValue
+ })
+ }
+}
+```
+
+Reload the page and use the web inspector to confirm the controller element’s data-slideshow-index-value attribute changes as you move from one slide to the next.
+
+
+## Change Callbacks
+
+修正したコントローラは元のバージョンより改善されていますが、`this.showCurrentSlide()`を繰り返し呼び出しているのが目立ちます。 コントローラの初期化時と、`this.indexValue`を更新した時にたびたびドキュメントの状態を手動で更新しなければなりません。
+
+Stimulusの`ValueChanged`コールバックを定義することで、繰り返しを一掃し、インデックス値が変更されるたびにコントローラがどのように応答すべきかを指定することができます。
+
+まず、`initialize()`メソッドを削除し、新しいメソッド`indexValueChanged()`を定義します。 次に、`next()`と`previous()`から`this.showCurrentSlide()`の呼び出しを削除します:
+
+```javascript
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ static targets = [ "slide" ]
+ static values = { index: Number }
+
+ next() {
+ this.indexValue++
+ }
+
+ previous() {
+ this.indexValue--
+ }
+
+ indexValueChanged() {
+ this.showCurrentSlide()
+ }
+
+ showCurrentSlide() {
+ this.slideTargets.forEach((element, index) => {
+ element.hidden = index !== this.indexValue
+ })
+ }
+}
+```
+
+ページをリロードし、スライドショーの動作が同じであることを確認しましょう。
+
+Stimulusは初期化時および`data-slideshow-index-value`属性の変更に応じて`indexValueChanged()`メソッドを呼び出します。 Webインスペクタで属性をいじれば、コントローラがそれに応答してスライドを変更します。 ぜひ試してみてください!
+
+
+原文
+
+## Change Callbacks
+
+Our revised controller improves on the original version, but the repeated calls to this.showCurrentSlide() stand out. We have to manually update the state of the document when the controller initializes and after every place where we update this.indexValue.
+
+We can define a Stimulus value change callback to clean up the repetition and specify how the controller should respond whenever the index value changes.
+
+First, remove the initialize() method and define a new method, indexValueChanged(). Then remove the calls to this.showCurrentSlide() from next() and previous():
+
+```javascript
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ static targets = [ "slide" ]
+ static values = { index: Number }
+
+ next() {
+ this.indexValue++
+ }
+
+ previous() {
+ this.indexValue--
+ }
+
+ indexValueChanged() {
+ this.showCurrentSlide()
+ }
+
+ showCurrentSlide() {
+ this.slideTargets.forEach((element, index) => {
+ element.hidden = index !== this.indexValue
+ })
+ }
+}
+```
+
+Reload the page and confirm the slideshow behavior is the same.
+
+Stimulus calls the indexValueChanged() method at initialization and in response to any change to the data-slideshow-index-value attribute. You can even fiddle with the attribute in the web inspector and the controller will change slides in response. Go ahead—try it out!
+
+
+### デフォルト値を指定する
+
+`static values`の行を少し変更すればデフォルト値を設定することも可能です。 デフォルト値の指定は次のように行います:
+
+```javascript
+static values = { index: { type: Number, default: 2 } }
+```
+
+controller要素に`data-slideshow-index-value`属性が定義されていなければ、インデックスを2から開始します。 他の値があれば、デフォルトが必要なものとそうでないものを混在させることができます:
+
+```javascript
+static values = { index: Number, effect: { type: String, default: "kenburns" } }
+```
+
+
+原文
+
+### Setting Defaults
+
+It’s also possible to set a default values as part of the static definition. This is done like so:
+
+```javascript
+ static values = { index: { type: Number, default: 2 } }
+```
+
+That would start the index at 2, if no data-slideshow-index-value attribute was defined on the controller element. If you had other values, you can mix and match what needs a default and what doesn’t:
+
+```javascript
+ static values = { index: Number, effect: { type: String, default: "kenburns" } }
+```
+
+
+## おさらいと次のステップ
+
+この章では、`values`を使用してスライドショーコントローラの現在のインデックス値を読み取り、永続化する方法について見てきました。
+
+ユーザビリティの観点からは、このコントローラは不完全です。最初のスライドを表示している時、Previousボタンは何もしてくれません。 内部的には、`indexValue`は`0`から`-1`まで減少します。 `-1`の代わりに、値を最後のスライドインデックスにして、ループするようにしたいですね(Nextボタンにも同様の問題があります)。
+
+次の章では、Stimulusコントローラで外部リソースにアクセスする方法を見ていきます。
+
+
+
+原文
+
+## Wrap-Up and Next Steps
+
+In this chapter we’ve seen how to use the values to load and persist the current index of a slideshow controller.
+
+From a usability perspective, our controller is incomplete. The Previous button appears to do nothing when you are looking at the first slide. Internally, indexValue decrements from 0 to -1. Could we make the value wrap around to the last slide index instead? (There’s a similar problem with the Next button.)
+
+Next we’ll look at how to keep track of external resources, such as timers and HTTP requests, in Stimulus controllers.
+
diff --git a/stimulus/handbook/origin.md b/stimulus/handbook/origin.md
new file mode 100644
index 00000000..2a315578
--- /dev/null
+++ b/stimulus/handbook/origin.md
@@ -0,0 +1,188 @@
+---
+title: "Stimulusの原点"
+description: "Stimulusが他のフレームワークとどう違うか、何を求められて生まれたものかについて"
+order: 0
+---
+
+# Stimulusの原点
+
+[Basecamp](https://basecamp.com/)ではJavaScriptをたくさん書いていますが、現代的な意味での「JavaScriptアプリケーション」を作るためにJavaScriptを使っているわけではありません。 Basecampのアプリケーションは、サーバーサイドでレンダリングされたHTMLを核に、JavaScriptを散りばめるようにしてできています。
+
+これが、[Majestic Monolith](https://signalvnoise.com/svn3/the-majestic-monolith/)のやり方です。 Basecampは、Ruby on Railsで作成された単一のコントローラ、ビュー、モデルで、ネイティブモバイルアプリを含む6つのプラットフォームで動作しています。 一箇所で更新可能な単一の共有インターフェイスを持つということは、多くのプラットフォームがあるにもかかわらず、少人数のチームで業務を遂行するための鍵となっています。
+
+それによって、昔のような高い生産性を体験できます。 一人のプログラマーが、間接的なレイヤーや分散システムに囚われることなく、貪欲に前進することができた時代に戻るのです。 JavaScriptベースのクライアントアプリケーションのために、サーバーサイドアプリケーションに、ただただJSONの生成だけをさせることが正しい方法だと皆が考える前の時代です。
+
+だからと言って、そのような現代のアプローチに一切価値がないと言っているわけではありません。 多くのアプリケーション、そしてBasecampのようなものへの一般的なアプローチとしては、全体的なシンプルさと生産性が後退しているというだけです。
+
+また、シングルページのJavaScriptアプリケーションが増えたからといって、本当にメリットがないわけでもありません。 主なメリットとして、フルページリフレッシュから解放された、より高速でより滑らかなインターフェースです。
+
+私たちは、Basecampもそんな風にしたかった。 まるで私たちがそういったムーブメントの後追いをして、すべてをクライアント側のレンダリングに書き直したり、フルネイティブのアプリにしたのかとみんなが錯覚するように。
+
+この思いが、私たちを2つの解決策へと導きました:[Turbo](/)とStimulusです。
+
+
+
+原文
+
+# The Origin of Stimulus
+
+We write a lot of JavaScript at Basecamp, but we don’t use it to create “JavaScript applications” in the contemporary sense. All our applications have server-side rendered HTML at their core, then add sprinkles of JavaScript to make them sparkle.
+
+This is the way of the majestic monolith. Basecamp runs across half a dozen platforms, including native mobile apps, with a single set of controllers, views, and models created using Ruby on Rails. Having a single, shared interface that can be updated in a single place is key to being able to perform with a small team, despite the many platforms.
+
+It allows us to party with productivity like days of yore. A throwback to when a single programmer could make rapacious progress without getting stuck in layers of indirection or distributed systems. A time before everyone thought the holy grail was to confine their server-side application to producing JSON for a JavaScript-based client application.
+
+That’s not to say that there isn’t value in such an approach for some people, some of the time. Just that as a general approach to many applications, and certainly the likes of Basecamp, it’s a regression in overall simplicity and productivity.
+
+And it’s also not to say that the proliferation of single-page JavaScript applications hasn’t brought real benefits. Chief amongst which has been faster, more fluid interfaces set free from the full-page refresh.
+
+We wanted Basecamp to feel like that too. As though we had followed the herd and rewritten everything with client-side rendering or gone full-native on mobile.
+
+This desire led us to a two-punch solution: Turbo and Stimulus.
+
+
+### Turboは高く、Stimulusは低く
+
+新しい控えめなJavaScriptフレームワークであるStimulusの説明に入る前に、Turboの命題をおさらいしておきましょう。
+
+Turboは、GitHubで開発された[pjax](https://github.com/defunkt/jquery-pjax)というアプローチから派生したものです。 基本的なコンセプトは変わりません。 ページのリフレッシュがしばしば遅く感じられるのは、ブラウザがサーバーから送られてくる大量のHTMLを処理しなければならないからというわけではありません。 ブラウザーは本当に優秀で高速です。 また、ほとんどの場合、HTMLのペイロードがJSONのペイロードよりも大きくなる傾向があるということも重要ではありません(特にgzipの場合)。 そうではなく、遅く感じる本当の理由はCSSとJavaScriptを再初期化してページに再適用しなければならないというところにあります。 ファイル自体がキャッシュされているかどうかは関係ありません。 かなりの量のCSSやJavaScriptがある場合、これによってかなり遅くなります。
+
+この再初期化を回避するために、Turboはシングルページのアプリケーションと同じように永続的なプロセスを維持します。 しかし、動作の大部分は透過的で目に見えないものです。 リンクをインターセプトし、Ajax経由で新しいページをロードします。 サーバーは依然として完全な形のHTMLドキュメントを返します。
+
+この戦略だけで、たいていのアプリケーションのほとんどのアクションが、(100〜200msで(キャッシュを使えば実現可能)サーバのレスポンスを返すことができれば)とても速く感じられるようになります。 Basecampでは、ページ間の遷移が約3倍速くなりました。 シングルページアプリケーションの魅力の大部分であった応答性と流動性をアプリケーションに与えることができました。
+
+しかし、Turboだけではまだまだ話の半分に過ぎません。 ページの全更新よりももっと細かいものの実装にも目を向ける必要があります。 要素の表示・非表示の切り替え、クリップボードへのコンテンツのコピー、リストへの新しいTODOの追加といった私たちがモダンなウェブアプリケーションでイメージするようなインタラクションの実現の方法についてです。
+
+Stimulus以前は、Basecampは様々なスタイルやパターンを使って、これらのモダンインタラクションを実現していました。 あるコードはjQueryをひとつまみ、あるコードはバニラJavaScriptを同じ大きさでひとつまみ、またあるコードはより大きなオブジェクト指向のサブシステムを使いました。 それらはすべて、[`data-behavior`属性](https://signalvnoise.com/posts/3167-code-spelunking-in-the-all-new-basecamp#:~:text=javascript%20behaviors)に指定した明示的なイベント処理で動かしていました。
+
+このように新しいコードを追加するのは簡単でしたが、包括的な解決策にはならず、社内にはあまりにも多くのスタイルやパターンが共存していました。 そのためコードを再利用することが難しく、新しい開発者が一貫したアプローチを学ぶことも難しかったのです。
+
+
+原文
+
+### Turbo up high, Stimulus down low
+
+Before I get to Stimulus, our new modest JavaScript framework, allow me to recap the proposition of Turbo.
+
+Turbo descends from an approach called pjax, developed at GitHub. The basic concept remains the same. The reason full-page refreshes often feel slow is not so much because the browser has to process a bunch of HTML sent from a server. Browsers are really good and really fast at that. And in most cases, the fact that an HTML payload tends to be larger than a JSON payload doesn’t matter either (especially with gzipping). No, the reason is that CSS and JavaScript has to be reinitialized and reapplied to the page again. Regardless of whether the files themselves are cached. This can be pretty slow if you have a fair amount of CSS and JavaScript.
+
+To get around this reinitialization, Turbo maintains a persistent process, just like single-page applications do. But largely an invisible one. It intercepts links and loads new pages via Ajax. The server still returns fully-formed HTML documents.
+
+This strategy alone can make most actions in most applications feel really fast (if they’re able to return server responses in 100-200ms, which is eminently possible with caching). For Basecamp, it sped up the page-to-page transition by ~3x. It gives the application that feel of responsiveness and fluidity that was a massive part of the appeal for single-page applications.
+
+But Turbo alone is only half the story. The coarsely grained one. Below the grade of a full page change lies all the fine-grained fidelity within a single page. The behavior that shows and hides elements, copies content to a clipboard, adds a new todo to a list, and all the other interactions we associate with a modern web application.
+
+Prior to Stimulus, Basecamp used a smattering of different styles and patterns to apply these sprinkles. Some code was just a pinch of jQuery, some code was a similarly sized pinch of vanilla JavaScript, and some again was larger object-oriented subsystems. They all usually worked off explicit event handling hanging off a data-behavior attribute.
+
+While it was easy to add new code like this, it wasn’t a comprehensive solution, and we had too many in-house styles and patterns coexisting. That made it hard to reuse code, and it made it hard for new developers to learn a consistent approach.
+
+
+### Stimulusの3つのコアコンセプト
+
+Stimulusは、これらのパターンの良いところをまとめあげ、コントローラー、アクション、ターゲットという3つの主要な概念だけを中心とした、控えめで小さなフレームワークです。
+
+Stimulusが適用されたHTMLを見ると、プログレッシブエンハンスメントとして読めるように設計されています。 1つのテンプレートを見るだけで、どんな振る舞いが要素に作用しているのかを知ることができます。 以下に例を示します。
+
+```html
+
+ PIN:
+
+
+```
+
+これを読めば、何が起こっているのかがよく分かると思います。 Stimulusについて何も知らなくても、コントローラのコードそのものを見なくても。 ほとんど擬似コードのようなものですね。 これは、イベントハンドラが外部のJavaScriptファイルで設定されているHTMLを読み取ることとは大きく異なります。 また、現代のJavaScriptフレームワークの多くで失われている関心事の分離も維持されています。
+
+見てわかるように、StimulusはHTMLの作成に悩まされることはありません。 JavaScriptでHTMLを作成するのではなく、既存のHTMLドキュメントにアタッチします。 HTMLは、ほとんどの場合、ページロード時(最初のヒットまたはTurbo経由)、またはDOMを変更するAjaxリクエスト経由のいずれかの時にサーバ側でレンダリングされます。
+
+Stimulusは、こうして作られた既存のHTML文書を操作することに主眼をおいています。 時にStimulusは、要素を隠したり、アニメーションさせたり、ハイライトさせたりするCSSクラスを追加したりします。 グループ化された要素を再配置することもあります。 キャッシュ可能なUTC時間を表示可能なローカル時間に変換する場合もそうです。
+
+時にはStimulusに新しいDOM要素を作成させたい場合もあるでしょう。 将来的には、それを簡単にするための方法も追加するかもしれません。 しかし、それはあまり多くない使用例です。 私たちは要素を作成するのではなく、操作することに重点を置いています。
+
+
+原文
+
+### The three core concepts in Stimulus
+
+Stimulus rolls up the best of those patterns into a modest, small framework revolving around just three main concepts: Controllers, actions, and targets.
+
+It’s designed to read as a progressive enhancement when you look at the HTML it’s addressing. Such that you can look at a single template and know which behavior is acting upon it. Here’s an example:
+
+```html
+
+ PIN:
+
+
+```
+
+You can read that and have a pretty good idea of what’s going on. Even without knowing anything about Stimulus or looking at the controller code itself. It’s almost like pseudocode. That’s very different from reading a slice of HTML that has an external JavaScript file apply event handlers to it. It also maintains the separation of concerns that has been lost in many contemporary JavaScript frameworks.
+
+As you can see, Stimulus doesn’t bother itself with creating the HTML. Rather, it attaches itself to an existing HTML document. The HTML is, in the majority of cases, rendered on the server either on the page load (first hit or via Turbo) or via an Ajax request that changes the DOM.
+
+Stimulus is concerned with manipulating this existing HTML document. Sometimes that means adding a CSS class that hides an element or animates it or highlights it. Sometimes it means rearranging elements in groupings. Sometimes it means manipulating the content of an element, like when we transform UTC times that can be cached into local times that can be displayed.
+
+There are cases where you’d want Stimulus to create new DOM elements, and you’re definitely free to do that. We might even add some sugar to make it easier in the future. But it’s the minority use case. The focus is on manipulating, not creating elements.
+
+
+### Stimulusと主流のJavaScriptフレームワークとの違い
+
+そのため、Stimulusは現代のJavaScriptフレームワークの大半とは大きく異なっています。 ほとんどすべてのフレームワークは、ある種のテンプレート言語を介してJSONをDOM要素に変換することに重点を置いています。 これらのフレームワークの多くは、空のページを作成し、そのページをJSONを元にしたテンプレートレンダリングによって作成された要素のみで埋めるために使用します。
+
+Stimulusはまた、ステートの扱いに関しても他のフレームワークと大きく異なります。 ほとんどのフレームワークは、JavaScriptオブジェクト内に状態を保持する方法を持ち、その状態に基づいてHTMLをレンダリングします。Stimulusは正反対の方法をとります。 ステートはHTML上に保存されます。 そのため、ページの変更の際にコントローラは破棄されますが、HTMLがキャッシュから再び表示されたときに元のステートを維持したまま復元することができます。
+
+これは本当に驚くほど異なるパラダイムです。 現代のフレームワークを使い慣れたJavaScript開発者の多くは、これを馬鹿にし、あざ笑うことだと思います。 React + Reduxのような大混乱の中でアプリケーションを維持するのにかかる複雑さと労力に満足しているなら、Turbo + Stimulusはあなたにとって魅力的なものではないかもしれません。
+
+その一方で、あなたが今取り組んでいることが、そのような現代的なテクニックが意味するような強烈な複雑さやアプリケーションの分離を正当化するものではないと強く感じているのであれば、私たちのアプローチに救いを見出すことができるでしょう。
+
+
+原文
+
+### How Stimulus differs from mainstream JavaScript frameworks
+
+This makes Stimulus very different from the majority of contemporary JavaScript frameworks. Almost all are focused on turning JSON into DOM elements via a template language of some sort. Many use these frameworks to birth an empty page, which is then filled exclusively with elements created through this JSON-to-template rendering.
+
+Stimulus also differs on the question of state. Most frameworks have ways of maintaining state within JavaScript objects, and then render HTML based on that state. Stimulus is the exact opposite. State is stored in the HTML, so that controllers can be discarded between page changes, but still reinitialize as they were when the cached HTML appears again.
+
+It really is a remarkably different paradigm. One that I’m sure many veteran JavaScript developers who’ve been used to work with contemporary frameworks will scoff at. And hey, scoff away. If you’re happy with the complexity and effort it takes to maintain an application within the maelstrom of, say, React + Redux, then Turbo + Stimulus will not appeal to you.
+
+If, on the other hand, you have nagging sense that what you’re working on does not warrant the intense complexity and application separation such contemporary techniques imply, then you’re likely to find refuge in our approach.
+
+
+### Stimulusと関連するアイデアは、自然に抽出されたもの
+
+Basecampでは、このアーキテクチャをBasecampのいくつかのバージョンや他のアプリケーションで長年使ってきました。 GitHubも同様のアプローチで大きな効果を上げています。 これは、 「モダンな」 Webアプリケーションがどのようなものであるかについての主流の考え方に対する有効な代替案であるだけでなく、信じられないほど説得力のあるものです。
+
+実際のところ、現代の主流なアプローチは無駄に複雑で、もっと速く、もっと少ないコストでできるはずだという、私たちがBasecampで[Ruby on Rails](https://rubyonrails.org/)を開発した時と同じような感覚があるのです。
+
+しかも、選ぶ必要もありません。 StimulusとTurboは、他の重いアプローチと組み合わせても効果的です。アプリケーションの80%が重たいアプローチを必要としない場合は、Stimulus、Turboの使用をご検討ください。 そして、本当にメリットがある部分にだけ、重たいアプローチの導入を検討しましょう。
+
+Basecampでも、必要に応じて、いくつかの重たいアプローチを採用しています。 たとえばカレンダーみたいなものははクライアントサイドレンダリングを使っています。 Basecamp上のテキストエディタは[Trix](https://trix-editor.org/)で、これはStimulusのコントローラとは関係のない完全なテキストプロセッサです。
+
+この一連の代替フレームワークのセットは、重い仕事をできるだけ避けるためのものです。 このシンプルなモデルでうまく機能する多くのインタラクションのために、リクエスト-レスポンスパラダイムに留まるのです。 そして、最高の忠実度が求められるときだけ、高価なツールに手を伸ばせばよいのです。
+
+とりわけ、このツールキットは、より手間のかかる主流のアプローチを用いる大規模なチームと、忠実さと到達度で競い合いたい小規模チームのためのものです。
+
+ぜひお試しください。
+
+David Heinemeier Hansson
+
+
+原文
+
+### Stimulus and related ideas were extracted from the wild
+
+At Basecamp we’ve used this architecture across several different versions of Basecamp and other applications for years. GitHub has used a similar approach to great effect. This is not only a valid alternative to the mainstream understanding of what a “modern” web application looks like, it’s an incredibly compelling one.
+
+In fact, it feels like the same kind of secret sauce we had at Basecamp when we developed Ruby on Rails. The sense that contemporary mainstream approaches are needlessly convoluted, and that we can do more, faster, with far less.
+
+Furthermore, you don’t even have to choose. Stimulus and Turbo work great in conjunction with other, heavier approaches. If 80% of your application does not warrant the big rig, consider using our two-pack punch for that. Then roll out the heavy machinery for the part of your application that can really benefit from it.
+
+At Basecamp, we have and do use several heavier-duty approaches when the occasion calls for it. Our calendars tend to use client-side rendering. Our text editor is Trix, a fully formed text processor that wouldn’t make sense as a set of Stimulus controllers.
+
+This set of alternative frameworks is about avoiding the heavy lifting as much as possible. To stay within the request-response paradigm for all the many, many interactions that work well with that simple model. Then reaching for the expensive tooling when there’s a call for peak fidelity.
+
+Above all, it’s a toolkit for small teams who want to compete on fidelity and reach with much larger teams using more laborious, mainstream approaches.
+
+Give it a go.
+
+David Heinemeier Hansson
+
diff --git a/stimulus/handbook/working-with-external-resources.md b/stimulus/handbook/working-with-external-resources.md
new file mode 100644
index 00000000..12829e97
--- /dev/null
+++ b/stimulus/handbook/working-with-external-resources.md
@@ -0,0 +1,458 @@
+---
+title: "外部リソースの利用"
+description: "Stimulusで外部リソースを取得して情報を更新したり、タイマーを使ったりする方法を見ていきましょう。"
+order: 6
+---
+
+# 外部リソースの利用
+
+前章では、valuesを使用してコントローラの内部状態をロードし、永続化する方法を学びました。
+
+時折コントローラーは外部リソースの状態を取得しなければならない場合があります。 ここでの外部とは、DOMやStimulusの一部ではないものを指します。 例えば、HTTPリクエストを発行し、リクエストの状態の変化に応じて応答する必要があるかもしれません。 あるいは、タイマーを開始し、コントローラがdisconnectした時にタイマーを停止する必要があるかもしれません。 この章では、こういったケースに対応するための方法を説明します。
+
+
+原文
+
+# Working With External Resources
+
+In the last chapter we learned how to load and persist a controller’s internal state using values.
+
+Sometimes our controllers need to track the state of external resources, where by external we mean anything that isn’t in the DOM or a part of Stimulus. For example, we may need to issue an HTTP request and respond as the request’s state changes. Or we may want to start a timer and then stop it when the controller is no longer connected. In this chapter we’ll see how to do both of those things.
+
+
+## HTMLの非同期読み込み
+
+リモートのHTMLスニペットを読み込んで挿入することで、ページの一部を非同期に生成する方法を学びましょう。 Basecampでは、このテクニックを使うことで、最初のページ読み込みを高速に保ち、ビューにユーザー固有のコンテンツを含まないようにして、より効率的にキャッシュできるようにしています。
+
+汎用のコンテンツローダーコントローラを作成し、サーバから取得したHTMLスニペットを要素に埋め込みます。 そして、それを使って、メールの受信トレイにあるような未読メッセージのリストを読み込みます。
+
+`public/index.html`に受信トレイをスケッチすることから始めましょう:
+
+```javascript
+
+```
+
+次に、メッセージ・リスト用のHTMLを含む`public/messages.html`ファイルを新規作成します:
+
+```javascript
+
+ - New Message: Stimulus Launch Party
+ - Overdue: Finish Stimulus 1.0
+
+```
+
+(実際のアプリケーションでは、このHTMLをサーバー上で動的に生成することになるが、デモでは静的なファイルを使うことにします)
+
+これで、コントローラを実装できるようになりました:
+
+```javascript
+// src/controllers/content_loader_controller.js
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ static values = { url: String }
+
+ connect() {
+ this.load()
+ }
+
+ load() {
+ fetch(this.urlValue)
+ .then(response => response.text())
+ .then(html => this.element.innerHTML = html)
+ }
+}
+```
+
+コントローラが接続されると、要素の`data-content-loader-url-value`属性で指定されたURLへのFetchリクエストを開始します。 そして、返されたHTMLを要素の`innerHTML`プロパティに代入して表示させます。
+
+ブラウザの開発者コンソールでネットワークタブを開き、ページをリロードします。 最初のページロードを表すリクエストと、それに続く`messages.html`へのリクエストが表示されましたね。
+
+
+原文
+
+## Asynchronously Loading HTML
+
+Let’s learn how to populate parts of a page asynchronously by loading and inserting remote fragments of HTML. We use this technique in Basecamp to keep our initial page loads fast, and to keep our views free of user-specific content so they can be cached more effectively.
+
+We’ll build a general-purpose content loader controller which populates its element with HTML fetched from the server. Then we’ll use it to load a list of unread messages like you’d see in an email inbox.
+
+Begin by sketching the inbox in public/index.html:
+
+```javascript
+
+```
+
+Then create a new public/messages.html file with some HTML for our message list:
+
+```javascript
+
+ - New Message: Stimulus Launch Party
+ - Overdue: Finish Stimulus 1.0
+
+```
+
+(In a real application you’d generate this HTML dynamically on the server, but for demonstration purposes we’ll just use a static file.)
+
+Now we can implement our controller:
+
+```javascript
+// src/controllers/content_loader_controller.js
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ static values = { url: String }
+
+ connect() {
+ this.load()
+ }
+
+ load() {
+ fetch(this.urlValue)
+ .then(response => response.text())
+ .then(html => this.element.innerHTML = html)
+ }
+}
+```
+
+When the controller connects, we kick off a Fetch request to the URL specified in the element’s data-content-loader-url-value attribute. Then we load the returned HTML by assigning it to our element’s innerHTML property.
+
+Open the network tab in your browser’s developer console and reload the page. You’ll see a request representing the initial page load, followed by our controller’s subsequent request to messages.html.
+
+
+## タイマーを利用した自動更新
+
+受信トレイを定期的に更新し、常に最新の状態にするようにコントローラを改善してみましょう。
+
+`data-content-loader-refresh-interval-value`属性を新たに作り、コントローラの内容をリロードする頻度をミリ秒単位で指定できるようにしましょう:
+
+```javascript
+
+```
+
+これで、設定したインターバルでコントローラをチェックし、存在すれば更新するように実装することができます。
+
+コントローラで`static values`の定義に、HTML側に記述した`url`と`refreshInterval`の二つを追加し、新しいメソッド`startRefreshing()`を定義します:
+
+```javascript
+export default class extends Controller {
+ static values = { url: String, refreshInterval: Number }
+
+ startRefreshing() {
+ setInterval(() => {
+ this.load()
+ }, this.refreshIntervalValue)
+ }
+
+ // …
+}
+```
+
+次に、`connect()`メソッドを更新して、インターバル値が存在する場合は`startRefreshing()`メソッドを呼び出すようにしましょう:
+
+```javascript
+connect() {
+ this.load()
+
+ if (this.hasRefreshIntervalValue) {
+ this.startRefreshing()
+ }
+}
+```
+
+ページをリロードし、開発者コンソールを見てみましょう。 5秒に一度、新しいリクエストが飛んでいることがわかります。 それが確認できたら`public/messages.html`に変更を加えて、その変更後のメッセージが受信箱に表示されるのを待ちましょう。
+
+
+
+原文
+
+## Refreshing Automatically With a Timer
+
+Let’s improve our controller by changing it to periodically refresh the inbox so it’s always up-to-date.
+
+We’ll use the data-content-loader-refresh-interval-value attribute to specify how often the controller should reload its contents, in milliseconds:
+
+```javascript
+
+```
+
+Now we can update the controller to check for the interval and, if present, start a refresh timer.
+
+Add a static values definition to the controller, and define a new method startRefreshing():
+
+```javascript
+export default class extends Controller {
+ static values = { url: String, refreshInterval: Number }
+
+ startRefreshing() {
+ setInterval(() => {
+ this.load()
+ }, this.refreshIntervalValue)
+ }
+
+ // …
+}
+```
+
+Then update the connect() method to call startRefreshing() if an interval value is present:
+
+```javascript
+ connect() {
+ this.load()
+
+ if (this.hasRefreshIntervalValue) {
+ this.startRefreshing()
+ }
+ }
+```
+
+Reload the page and observe a new request once every five seconds in the developer console. Then make a change to public/messages.html and wait for it to appear in the inbox.
+
+
+## リソースの取得のインターバルの解除
+
+今のままではコントローラが接続されたときにタイマーは開始されますが、決して停止することはありません。 つまり、コントローラに対応する要素が消えてしまった場合でも、 コントローラはバックグラウンドでHTTPリクエストを投げ続けることになってしまいます。
+
+この問題を解決するに、`startRefreshing()`メソッドを変更してタイマーへの参照を保持するようにします:
+
+```javascript
+startRefreshing() {
+ this.refreshTimer = setInterval(() => {
+ this.load()
+ }, this.refreshIntervalValue)
+}
+```
+
+そして、対応する`stopRefreshing()`メソッドを下に追加して、タイマーをキャンセルすることができるように実装します:
+
+```javascript
+stopRefreshing() {
+ if (this.refreshTimer) {
+ clearInterval(this.refreshTimer)
+ }
+}
+```
+
+最後に、コントローラが切断されたときにタイマーをキャンセルするようにStimulusに指示するために、`disconnect()`メソッドを追加します:
+
+```javascript
+disconnect() {
+ this.stopRefreshing()
+}
+```
+
+これで、コンテンツローダーコントローラーが、DOMに接続されている間だけリクエストを発行するように修正することができました。
+
+完成系のコントローラを見てみましょう:
+
+```javascript
+// src/controllers/content_loader_controller.js
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ static values = { url: String, refreshInterval: Number }
+
+ connect() {
+ this.load()
+
+ if (this.hasRefreshIntervalValue) {
+ this.startRefreshing()
+ }
+ }
+
+ disconnect() {
+ this.stopRefreshing()
+ }
+
+ load() {
+ fetch(this.urlValue)
+ .then(response => response.text())
+ .then(html => this.element.innerHTML = html)
+ }
+
+ startRefreshing() {
+ this.refreshTimer = setInterval(() => {
+ this.load()
+ }, this.refreshIntervalValue)
+ }
+
+ stopRefreshing() {
+ if (this.refreshTimer) {
+ clearInterval(this.refreshTimer)
+ }
+ }
+}
+```
+
+
+原文
+
+## Releasing Tracked Resources
+
+We start our timer when the controller connects, but we never stop it. That means if our controller’s element were to disappear, the controller would continue to issue HTTP requests in the background.
+
+We can fix this issue by modifying our startRefreshing() method to keep a reference to the timer:
+
+```javascript
+ startRefreshing() {
+ this.refreshTimer = setInterval(() => {
+ this.load()
+ }, this.refreshIntervalValue)
+ }
+```
+
+Then we can add a corresponding stopRefreshing() method below to cancel the timer:
+
+```javascript
+ stopRefreshing() {
+ if (this.refreshTimer) {
+ clearInterval(this.refreshTimer)
+ }
+ }
+```
+
+Finally, to instruct Stimulus to cancel the timer when the controller disconnects, we’ll add a disconnect() method:
+
+```javascript
+ disconnect() {
+ this.stopRefreshing()
+ }
+```
+
+Now we can be sure a content loader controller will only issue requests when it’s connected to the DOM.
+
+Let’s take a look at our final controller class:
+
+```javascript
+// src/controllers/content_loader_controller.js
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ static values = { url: String, refreshInterval: Number }
+
+ connect() {
+ this.load()
+
+ if (this.hasRefreshIntervalValue) {
+ this.startRefreshing()
+ }
+ }
+
+ disconnect() {
+ this.stopRefreshing()
+ }
+
+ load() {
+ fetch(this.urlValue)
+ .then(response => response.text())
+ .then(html => this.element.innerHTML = html)
+ }
+
+ startRefreshing() {
+ this.refreshTimer = setInterval(() => {
+ this.load()
+ }, this.refreshIntervalValue)
+ }
+
+ stopRefreshing() {
+ if (this.refreshTimer) {
+ clearInterval(this.refreshTimer)
+ }
+ }
+}
+```
+
+
+## アクションパラメータを利用する
+
+もしローダーを複数の異なるソースで動作させたいのであれば、アクションパラメーターが使えます。 次のHTMLを見てみましょう:
+
+```html
+
+```
+
+そうすれば、loadアクションでそのパラメーターを参照することができます:
+
+```javascript
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ load({ params }) {
+ fetch(params.url)
+ .then(response => response.text())
+ .then(html => this.element.innerHTML = html)
+ }
+}
+```
+
+paramsを分解して`url`パラメータだけを取得することもできます:
+
+```javascript
+load({ params: { url } }) {
+ fetch(url)
+ .then(response => response.text())
+ .then(html => this.element.innerHTML = html)
+}
+```
+
+
+ 原文
+
+## Using action parameters
+
+```html
+
+```
+
+Then we can use those parameters through the load action:
+
+```javascript
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ load({ params }) {
+ fetch(params.url)
+ .then(response => response.text())
+ .then(html => this.element.innerHTML = html)
+ }
+}
+```
+
+We could even destruct the params to just get the URL parameter:
+
+```javascript
+ load({ params: { url } }) {
+ fetch(url)
+ .then(response => response.text())
+ .then(html => this.element.innerHTML = html)
+ }
+```
+
+
+## おさらいと次のステップ
+
+この章では、Stimulus のライフサイクルコールバックを使用して外部リソースを取得および解放する方法を見てきました。
+
+次に、独自のアプリケーションにStimulus をインストールして設定する方法を説明します。
+
+
+原文
+
+## Wrap-Up and Next Steps
+
+In this chapter we’ve seen how to acquire and release external resources using Stimulus lifecycle callbacks.
+
+Next we’ll see how to install and configure Stimulus in your own application.
+
diff --git a/stimulus/reference/actions.md b/stimulus/reference/actions.md
new file mode 100644
index 00000000..ba9818a4
--- /dev/null
+++ b/stimulus/reference/actions.md
@@ -0,0 +1,703 @@
+---
+title: Actions
+description: "アクションはコントローラでDOMイベントを処理する方法です"
+order: 2
+---
+
+# Actions
+
+アクションは、コントローラでDOM イベントを処理する方法です。
+
+```html
+
+
+
+```
+
+```javascript
+// controllers/gallery_controller.js
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ next(event) {
+ // …
+ }
+}
+```
+
+アクションは次に示すものをつなぎあわせたものです。
+
+* コントローラのメソッド
+* コントロラー要素
+* DOMイベントリスナ
+
+
+ 原文
+
+_Actions_ are how you handle DOM events in your controllers.
+
+```html
+
+
+
+```
+
+```javascript
+// controllers/gallery_controller.js
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ next(event) {
+ // …
+ }
+}
+```
+
+An action is a connection between:
+
+* a controller method
+* the controller's element
+* a DOM event listener
+
+
+## Descriptors
+
+`data-action`属性の値である`click->gallery#next`は _アクション記述子_ と呼ばれます。 この記述子の場合は:
+
+* `click` は購読するDOMイベント名
+* `gallery` はコントローラの識別子
+* `next` は呼び出すメソッド前
+
+になります。
+
+
+ 原文
+
+The `data-action` value `click->gallery#next` is called an _action descriptor_. In this descriptor:
+
+* `click` is the name of the DOM event to listen for
+* `gallery` is the controller identifier
+* `next` is the name of the method to invoke
+
+
+### イベント省略記法
+
+Stimulusでは要素ごとにデフォルトのイベントが定められています。 デフォルトのイベントを購読する場合はアクション記述子内のイベント名を省略して、記述子全体を短くすることができます。
+
+上記のクリックイベントの購読はボタン要素に設定する場合、次のように記述できます。
+
+```html
+
+```
+
+以下の表は要素ごとのデフォルトイベントの一覧を示したものです。
+
+要素 | デフォルトイベント
+----------------- | -------------
+a | click
+button | click
+details | toggle
+form | submit
+input | input
+input type=submit | click
+select | change
+textarea | input
+
+
+
+ 原文
+
+Stimulus lets you shorten the action descriptors for some common element/event pairs, such as the button/click pair above, by omitting the event name:
+
+```html
+
+```
+
+The full set of these shorthand pairs is as follows:
+
+Element | Default Event
+----------------- | -------------
+a | click
+button | click
+details | toggle
+form | submit
+input | input
+input type=submit | click
+select | change
+textarea | input
+
+
+## キーボードイベントのフィルタ構文
+
+[KeyboardEvent](https://developer.mozilla.org/ja/docs/Web/API/KeyboardEvent)を購読する場合、特定のキーが押された時だけ処理を実行したいということもあると思います。
+
+以下の例のように、アクション記述子のイベント名の後に`.esc`を追加することで、`Escapeキー`にのみ反応するイベントリスナを設置することができます。
+
+```html
+
+
+```
+
+このフィルタ構文は、発生したイベントがキーボードイベントである場合にのみ機能します。
+
+以下の表はフィルタとキーの対応の一覧です。
+
+フィルタ | キー名
+--------- | --------
+enter | Enter
+tab | Tab
+esc | Escape
+space | " "
+up | ArrowUp
+down | ArrowDown
+left | ArrowLeft
+right | ArrowRight
+home | Home
+end | End
+page_up | PageUp
+page_down | PageDown
+[a-z] | [a-z]
+[0-9] | [0-9]
+
+ここにないキーをサポートする必要がある場合は、カスタムスキーマを使ってフィルタをカスタマイズすることができます。
+
+```javascript
+import { Application, defaultSchema } from "@hotwired/stimulus"
+
+const customSchema = {
+ ...defaultSchema,
+ keyMappings: { ...defaultSchema.keyMappings, at: "@" },
+}
+
+const app = Application.start(document.documentElement, customSchema)
+```
+
+修飾キーを使った複合的なイベントを購読したい場合は、`ctrl+a`のように書くことができます。
+
+```html
+
...
+```
+
+以下の表はStimulusがサポートする修飾キーの一覧です。
+
+| 修飾キー | ノート |
+| -------- | ------------------ |
+| `alt` | `option` (MacOS) |
+| `ctrl` | |
+| `meta` | `Command` (MacOS) |
+| `shift` | |
+
+
+ 原文
+There may be cases where [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent) Actions should only call the Controller method when certain keystrokes are used.
+
+You can install an event listener that responds only to the `Escape` key by adding `.esc` to the event name of the action descriptor, as in the following example.
+
+```html
+
+
+```
+
+This will only work if the event being fired is a keyboard event.
+
+The correspondence between these filter and keys is shown below.
+
+Filter | Key Name
+-------- | --------
+enter | Enter
+tab | Tab
+esc | Escape
+space | " "
+up | ArrowUp
+down | ArrowDown
+left | ArrowLeft
+right | ArrowRight
+home | Home
+end | End
+page_up | PageUp
+page_down | PageDown
+[a-z] | [a-z]
+[0-9] | [0-9]
+
+If you need to support other keys, you can customize the modifiers using a custom schema.
+
+```javascript
+import { Application, defaultSchema } from "@hotwired/stimulus"
+
+const customSchema = {
+ ...defaultSchema,
+ keyMappings: { ...defaultSchema.keyMappings, at: "@" },
+}
+
+const app = Application.start(document.documentElement, customSchema)
+```
+
+If you want to subscribe to a compound filter using a modifier key, you can write it like `ctrl+a`.
+
+```html
+...
+```
+
+The list of supported modifier keys is shown below.
+
+| Modifier | Notes |
+| -------- | ------------------ |
+| `alt` | `option` on MacOS |
+| `ctrl` | |
+| `meta` | Command key on MacOS |
+| `shift` | |
+
+
+### グローバルイベント
+
+しばしば`window`や`document`オブジェクトで発生するイベントを購読したいことがあります。
+
+次の例のように、アクション記述子のイベント名に(フィルター修飾子があっても良い)`@window`または`@document`を追加すると、それぞれ`window`または`document`にイベントを購読することができます:
+
+```html
+
+
+```
+
+
+ 原文
+
+Sometimes a controller needs to listen for events dispatched on the global `window` or `document` objects.
+
+You can append `@window` or `@document` to the event name (along with any filter modifier) in an action descriptor to install the event listener on `window` or `document`, respectively, as in the following example:
+
+```html
+
+
+```
+
+
+### アクションオプション
+
+[DOMイベントリスナのオプション](https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener#Parameters)は、アクション記述子に1つ以上のアクションオプションを追加することで指定できます。
+
+```html
+
+
![]()
+```
+
+Stimulusは次のアクションオプションをサポートしています。
+
+アクションオプション | 対応するDOMイベントリスナのオプション
+-------------------- | -----------------------------
+`:capture` | `{ capture: true }`
+`:once` | `{ once: true }`
+`:passive` | `{ passive: true }`
+`:!passive` | `{ passive: false }`
+
+これに加えて、Stimulusではネイティブにサポートされていない以下のアクションオプションをサポートしています:
+
+カスタムアクションオプション | 説明
+---------------------------- | -----------
+`:stop` | `.stopPropagation()` をメソッドの実行前に呼び出す
+`:prevent` | `.preventDefault()` をメソッドの実行前に呼び出す
+`:self` | イベントが自身の要素で発生した時のみメソッドを呼び出す
+
+独自のアクションオプションを新規に登録したい場合は、`Application.registerActionOption`メソッドを使用します。
+
+例えば、`
`要素が開閉されるたびにディスパッチする`toggleイベント`を、開かれた時だけにフィルタリングするカスタム`:open`アクションオプションを作れば、開かれた時だけにイベントをルーティングするのに役立ちます:
+
+```javascript
+import { Application } from "@hotwired/stimulus"
+
+const application = Application.start()
+
+application.registerActionOption("open", ({ event }) => {
+ if (event.type == "toggle") {
+ return event.target.open == true
+ } else {
+ return true
+ }
+})
+```
+
+アクションオプションに`!`のプレフィックスをつけた場合、アクションオプションを定義した関数の引数のプロパティ`value`に`false`が渡るため、以下のように変更すれば`:!open`アクションオプションで要素が閉じられる度にイベントをルーティングすることができるようになります。
+
+```javascript
+import { Application } from "@hotwired/stimulus"
+
+const application = Application.start()
+
+application.registerActionOption("open", ({ event, value }) => {
+ if (event.type == "toggle") {
+ return event.target.open == value
+ } else {
+ return true
+ }
+})
+```
+
+イベントがコントローラアクションにルーティングされないようにするには、`registerActionOption`のコールバック関数は`false`を返す必要があります。 逆に、イベントをコントローラのアクションにルーティングするためには、`true`を返します。
+
+このコールバックは、以下のキーを持つオブジェクト引数を受け取ります:
+
+| キー | 説明 |
+| ---------- | ----------------------------------------------------------------------------------------------------- |
+| name | String: オプション名 (例の場合であれば `"open"`) |
+| value | Boolean: オプションに`!`がついてるかどうか (`:open` であれば `true`, `:!open` なら `false` になる) |
+| event | Event: イベントの実体 (後述のアクションパラメータ `params` を含む) |
+| element | Element: アクション記述子を設定した要素 |
+| controller | 呼び出されるメソッドを持つコントローラの実体 |
+
+
+ 原文
+
+You can append one or more _action options_ to an action descriptor if you need to specify [DOM event listener options](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters).
+
+```html
+
+
![]()
+```
+
+Stimulus supports the following action options:
+
+Action option | DOM event listener option
+------------- | -------------------------
+`:capture` | `{ capture: true }`
+`:once` | `{ once: true }`
+`:passive` | `{ passive: true }`
+`:!passive` | `{ passive: false }`
+
+On top of that, Stimulus also supports the following action options which are not natively supported by the DOM event listener options:
+
+Custom action option | Description
+-------------------- | -----------
+`:stop` | calls `.stopPropagation()` on the event before invoking the method
+`:prevent` | calls `.preventDefault()` on the event before invoking the method
+`:self` | only invokes the method if the event was fired by the element itself
+
+You can register your own action options with the `Application.registerActionOption` method.
+
+For example, consider that a `
` element will dispatch a [toggle][]
+event whenever it's toggled. A custom `:open` action option would help
+to route events whenever the element is toggled _open_:
+
+```javascript
+import { Application } from "@hotwired/stimulus"
+
+const application = Application.start()
+
+application.registerActionOption("open", ({ event }) => {
+ if (event.type == "toggle") {
+ return event.target.open == true
+ } else {
+ return true
+ }
+})
+```
+
+Similarly, a custom `:!open` action option could route events whenever the
+element is toggled _closed_. Declaring the action descriptor option with a `!`
+prefix will yield a `value` argument set to `false` in the callback:
+
+```javascript
+import { Application } from "@hotwired/stimulus"
+
+const application = Application.start()
+
+application.registerActionOption("open", ({ event, value }) => {
+ if (event.type == "toggle") {
+ return event.target.open == value
+ } else {
+ return true
+ }
+})
+```
+
+In order to prevent the event from being routed to the controller action, the
+`registerActionOption` callback function must return `false`. Otherwise, to
+route the event to the controller action, return `true`.
+
+The callback accepts a single object argument with the following keys:
+
+| Name | Description |
+| ---------- | ----------------------------------------------------------------------------------------------------- |
+| name | String: The option's name (`"open"` in the example above) |
+| value | Boolean: The value of the option (`:open` would yield `true`, `:!open` would yield `false`) |
+| event | [Event][]: The event instance, including with the `params` action parameters on the submitter element |
+| element | [Element]: The element where the action descriptor is declared |
+| controller | The `Controller` instance which would receive the method call |
+
+[toggle]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLDetailsElement/toggle_event
+[Event]: https://developer.mozilla.org/en-US/docs/web/api/event
+[Element]: https://developer.mozilla.org/en-US/docs/Web/API/element
+
+
+
+## イベントオブジェクト
+
+_アクションメソッド_ は、アクションのイベントリスナとなるコントローラ内のメソッドです。
+
+アクションメソッドの最初の引数は _DOMイベントオブジェクト_ です。 イベントにアクセスしたい理由は、次のようなものがあります:
+
+* キーボードイベントからキーコードを読み取る
+* マウスイベントの座標を読み取る
+* 入力イベントからデータを読み取る
+* `submitter`となる要素からパラメータを読み取る
+* イベントに対するブラウザのデフォルト動作を阻止する
+* どの要素がこのイベントをディスパッチしたかを調べる
+
+以下の基本的なプロパティは、すべてのイベントに共通して存在します:
+
+Eventのプロパティ | 値
+------------------- | -----
+event.type | イベント名 (例. `"click"`)
+event.target | イベントをディスパッチした要素 (つまり、クリックされた最も内側の要素)
+event.currentTarget | イベントリスナが設定されてる要素 (`data-action`が設定されてる要素、あるいはグローバルリスナの場合 `document` か `window`)
+event.params | アクションの`submitter`となる要素から渡されるアクションパラメータ
+
+以下のイベントの持つメソッドを使えば、イベントの処理方法を細かく制御できます:
+
+Eventのメソッド | 結果
+----------------------- | ------
+event.preventDefault() | イベントのデフォルトの挙動をキャンセルする (例えばリンク先への遷移やフォームの送信など)
+event.stopPropagation() | 親要素へのイベントの伝播をストップさせる
+
+
+ 原文
+
+An _action method_ is the method in a controller which serves as an action's event listener.
+
+The first argument to an action method is the DOM _event object_. You may want access to the event for a number of reasons, including:
+
+* to read the key code from a keyboard event
+* to read the coordinates of a mouse event
+* to read data from an input event
+* to read params from the action submitter element
+* to prevent the browser's default behavior for an event
+* to find out which element dispatched an event before it bubbled up to this action
+
+The following basic properties are common to all events:
+
+Event Property | Value
+------------------- | -----
+event.type | The name of the event (e.g. `"click"`)
+event.target | The target that dispatched the event (i.e. the innermost element that was clicked)
+event.currentTarget | The target on which the event listener is installed (either the element with the `data-action` attribute, or `document` or `window`)
+event.params | The action params passed by the action submitter element
+
+
The following event methods give you more control over how events are handled:
+
+Event Method | Result
+----------------------- | ------
+event.preventDefault() | Cancels the event's default behavior (e.g. following a link or submitting a form)
+event.stopPropagation() | Stops the event before it bubbles up to other listeners on parent elements
+
+
+
+## マルチアクション
+
+`data-action`属性の値は、スペースで区切られたアクション記述子のリストです。
+
+任意の要素が複数のアクションを持つことはよくあります。 たとえば、次のinput要素は、フォーカスが当たった時に`field`コントローラの`highlight()` メソッドを呼び出し、要素の値が変わるたびに`search`コントローラの`update()`メソッドを呼び出します:
+
+```html
+
+```
+
+要素が同じイベントに対して複数のアクションを持つ場合、Stimulusは左から右へ、それらの記述子に記載示されている順にアクションを呼び出します。
+
+アクションの呼び出しチェーンは、アクション内で`Event#stopImmediatePropagation()`を呼び出すことで、任意の時点で停止させることができます。 その場合、呼び出された関数より右側に追加されたアクションは無視されます:
+
+```javascript
+highlight: function(event) {
+ event.stopImmediatePropagation()
+ // ...
+}
+```
+
+
+ 原文
+
+The `data-action` attribute's value is a space-separated list of action descriptors.
+
+It's common for any given element to have many actions. For example, the following input element calls a `field` controller's `highlight()` method when it gains focus, and a `search` controller's `update()` method every time the element's value changes:
+
+```html
+
+```
+
+When an element has more than one action for the same event, Stimulus invokes the actions from left to right in the order that their descriptors appear.
+
+The action chain can be stopped at any point by calling `Event#stopImmediatePropagation()` within an action. Any additional actions to the right will be ignored:
+
+```javascript
+highlight: function(event) {
+ event.stopImmediatePropagation()
+ // ...
+}
+```
+
+
+## 命名規則
+
+アクション名は、コントローラのメソッドに直接対応するので、常にキャメルケースで指定します。
+
+`click`や`onClick`、`handleClick`のように、単にイベント名を繰り返しただけのアクション名は避けましょう:
+
+```html
+
+```
+
+代わりに、呼び出された時に何が起こるかに基づいてアクションメソッドに名前をつけましょう:
+
+```html
+
+```
+
+これによって、コントローラのソースを見ることなく、要素の持つ振る舞いが予測できるようになります。
+
+
+ 原文
+
+Always use camelCase to specify action names, since they map directly to methods on your controller.
+
+Avoid action names that simply repeat the event's name, such as `click`, `onClick`, or `handleClick`:
+
+```html
+
+```
+
+Instead, name your action methods based on what will happen when they're called:
+
+```html
+
+```
+
+This will help you reason about the behavior of a block of HTML without having to look at the controller source.
+
+
+
+## アクションパラメータ
+
+アクションは`submitter`要素から渡されるパラメータを受け取ることができます。 パラメータは`data-[識別子]-[パラメータ名]-param`の書式で記述します。 パラメータは、渡したい先のアクションが宣言されている要素に指定する必要があります。
+
+すべてのパラメータは、その値から推測される`Number`、`String`、`Object`、`Boolean`のいずれかに自動的に型変換されます:
+
+data属性 | パラメータ | 型
+----------------------------------------------- | -------------------- | --------
+`data-item-id-param="12345"` | `12345` | Number
+`data-item-url-param="/votes"` | `"/votes"` | String
+`data-item-payload-param='{"value":"1234567"}'` | `{ value: 1234567 }` | Object
+`data-item-active-param="true"` | `true` | Boolean
+
+
+
以下の設定について考えてみよう:
+
+```html
+
+
+
+```
+
+この時、`ItemController#upvote`と`SpinnerController#start`の両方が呼び出されますが、識別子が`item`なのでパラメータが渡されるのは前者だけです:
+
+```javascript
+// ItemController
+upvote(event) {
+ // { id: 12345, url: "/votes", active: true, payload: { value: 1234567 } }
+ console.log(event.params)
+}
+
+// SpinnerController
+start(event) {
+ // {}
+ console.log(event.params)
+}
+```
+
+イベントオブジェクトの持つプロパティのうち、paramsの他に何も必要なければ、以下のように分解してparamsだけを受け取ることもできます:
+
+```javascript
+upvote({ params }) {
+ // { id: 12345, url: "/votes", active: true, payload: { value: 1234567 } }
+ console.log(params)
+}
+```
+
+Or destruct only the params we need, in case multiple actions on the same controller share the same submitter element:
+または、同じコントローラの複数のアクションが同じ`submitter`要素を共有しており、一方には不必要であるパラメータが混在している場合、必要なパラメータのみに分解して受け取ることもできます:
+
+```javascript
+upvote({ params: { id, url } }) {
+ console.log(id) // 12345
+ console.log(url) // "/votes"
+}
+```
+
+
+ 原文
+
+Actions can have parameters that are be passed from the submitter element. They follow the format of `data-[identifier]-[param-name]-param`. Parameters must be specified on the same element as the action they intend to be passed to is declared.
+
+All parameters are automatically typecast to either a `Number`, `String`, `Object`, or `Boolean`, inferred by their value:
+
+Data attribute | Param | Type
+----------------------------------------------- | -------------------- | --------
+`data-item-id-param="12345"` | `12345` | Number
+`data-item-url-param="/votes"` | `"/votes"` | String
+`data-item-payload-param='{"value":"1234567"}'` | `{ value: 1234567 }` | Object
+`data-item-active-param="true"` | `true` | Boolean
+
+
+
Consider this setup:
+
+```html
+
+
+
+```
+
+It will call both `ItemController#upvote` and `SpinnerController#start`, but only the former will have any parameters passed to it:
+
+```javascript
+// ItemController
+upvote(event) {
+ // { id: 12345, url: "/votes", active: true, payload: { value: 1234567 } }
+ console.log(event.params)
+}
+
+// SpinnerController
+start(event) {
+ // {}
+ console.log(event.params)
+}
+```
+
+If we don't need anything else from the event, we can destruct the params:
+
+```javascript
+upvote({ params }) {
+ // { id: 12345, url: "/votes", active: true, payload: { value: 1234567 } }
+ console.log(params)
+}
+```
+
+Or destruct only the params we need, in case multiple actions on the same controller share the same submitter element:
+
+```javascript
+upvote({ params: { id, url } }) {
+ console.log(id) // 12345
+ console.log(url) // "/votes"
+}
+```
+
diff --git a/stimulus/reference/controllers.md b/stimulus/reference/controllers.md
new file mode 100644
index 00000000..3cbf8f80
--- /dev/null
+++ b/stimulus/reference/controllers.md
@@ -0,0 +1,583 @@
+---
+title: Controllers
+description: "コントローラはStimulusアプリケーションの基本的な構成単位です"
+order: 0
+---
+
+# Controllers
+
+コントローラは、Stimulusアプリケーションの基本的な構成単位です。
+
+```javascript
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ // …
+}
+```
+
+コントローラーは、アプリケーションで定義するJavaScriptクラスのインスタンスです。 各コントローラクラスは、`@hotwired/stimulus`モジュールによってエクスポートされた`Controller`基底クラスを継承します。
+
+
+ 原文
+
+A controller is the basic organizational unit of a Stimulus application.
+
+```javascript
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ // …
+}
+```
+
+Controllers are instances of JavaScript classes that you define in your application. Each controller class inherits from the Controller base class exported by the @hotwired/stimulus module.
+
+
+## プロパティ
+
+すべてのコントローラーはStimulus Applicationインスタンスに属し、HTML要素に関連付けられます。 コントローラクラス内では...
+
+* `this.application`プロパティで`application`に
+* `this.element`プロパティでコントローラを設定したHTML要素に
+* `this.identifier`プロパティでコントローラ名に
+
+それぞれアクセスすることができます。
+
+
+ 原文
+
+Every controller belongs to a Stimulus Application instance and is associated with an HTML element. Within a controller class, you can access the controller’s:
+
+* application, via the this.application property
+* HTML element, via the this.element property
+* identifier, via the this.identifier property
+
+
+## モジュール
+
+コントローラクラスは1ファイルに1つずつJavaScriptモジュール形式で定義します。 前述の例のように、各コントローラクラスをモジュールのデフォルトオブジェクトとしてエクスポートします。
+
+これらのモジュールを`controllers/`ディレクトリに置きます。 ファイル名は`[識別子]_controller.js`とし、`[識別子]`には各コントローラの識別子が入ります。
+
+
+ 原文
+
+Define your controller classes in JavaScript modules, one per file. Export each controller class as the module’s default object, as in the example above.
+
+Place these modules in the controllers/ directory. Name the files [identifier]_controller.js, where [identifier] corresponds to each controller’s identifier.
+
+
+## コントローラ識別子
+
+`識別子`は、HTMLでコントローラークラスを参照するために使用する名前です。
+
+要素に`data-controller`属性を追加すると、Stimulusは属性の値から識別子を読み取り、対応するコントローラークラスの新しいインスタンスを作成します。
+
+たとえば、下記の要素には、`controllers/reference_controller.js` で定義されているコントローラクラスのインスタンスが割り当てられます。
+
+```html
+
+```
+
+以下に、Stimulusが識別子に対応するコントローラファイルを特定する時の対応関係を示します。
+
+| コントローラーファイルの名前 | 対応するコントローラ名 |
+|---|---|
+| clipboard_controller.js | clipboard |
+| date_picker_controller.js | date-picker |
+| users/list_item_controller.js | users--list-item |
+| local-time-controller.js| local-time |
+
+
+
+ 原文
+An identifier is the name you use to reference a controller class in HTML.
+
+When you add a data-controller attribute to an element, Stimulus reads the identifier from the attribute’s value and creates a new instance of the corresponding controller class.
+
+For example, this element has a controller which is an instance of the class defined in controllers/reference_controller.js:
+
+```html
+
+```
+
+The following is an example of how Stimulus will generate identifiers for controllers in its require context:
+
+| If your controller file is named…| its identifier will be… |
+|---|---|
+| clipboard_controller.js | clipboard |
+| date_picker_controller.js | date-picker |
+| users/list_item_controller.js | users--list-item |
+| local-time-controller.js| local-time |
+
+
+## スコープ
+
+Stimulus がコントローラを要素に接続すると、その要素とすべての子孫要素がコントローラのスコープになります。
+
+例えば、次のHTMLの`
`と`
`はコントローラのスコープに含まれますが、その外側の``要素はスコープに含まれません。
+
+```html
+
+
+
Reference
+
+
+```
+
+
+ 原文
+
+When Stimulus connects a controller to an element, that element and all of its children make up the controller’s scope.
+
+For example, the `` and `
` below are part of the controller’s scope, but the surrounding `` element is not.
+
+```html
+
+
+
Reference
+
+
+```
+
+
+## ネスト時のスコープ
+
+コントローラがネストしている場合、各コントローラは、内側のコントローラのスコープを除いた自分自身のスコープのみを認識します。
+
+たとえば、以下の`#parent`に設定された`list`コントローラは、そのスコープ内にあるアイテムのターゲットのみを認識し、`#child`に設定された`list`コントローラのターゲットは自身のターゲットとは認識しません。
+
+```html
+
+```
+
+
+ 原文
+When nested, each controller is only aware of its own scope excluding the scope of any controllers nested within.
+
+For example, the #parent controller below is only aware of the item targets directly within its scope, but not any targets of the #child controller.
+
+```html
+
+```
+
+
+## マルチコントローラ
+
+`data-controller`属性の値は、スペースで区切られた識別子のリストです:
+
+```html
+
+```
+
+ページ上の要素に複数のコントローラが設定されるのはよくあることです。 上の例では、``には`clipboard`と`list-item`という2つのコントローラが設定されています。
+
+同様に、ページ上の複数の要素に同じコントローラが適用されることもよくあります:
+
+```html
+
+```
+
+ここでは、それぞれの`
`ごとに`list-item`コントローラのインスタンスが生成されます。
+
+
+ 原文
+
+The data-controller attribute’s value is a space-separated list of identifiers:
+
+```html
+
+```
+
+It’s common for any given element on the page to have many controllers. In the example above, the `` has two connected controllers, clipboard and list-item.
+
+Similarly, it’s common for multiple elements on the page to reference the same controller class:
+
+```html
+
+```
+
+Here, each `
` has its own instance of the list-item controller.
+
+
+## 命名規則
+
+コントローラクラスのメソッド名やプロパティ名には、常にキャメルケースを使用します。
+
+識別子が複数の単語から構成される場合は、単語をケバブケースで記述します (つまり、次のようにダッシュを使用します: `date-picker`, `list-item`)。
+
+ファイル名は、複数の単語をアンダースコアまたはダッシュで区切ります(snake_caseまたはkebab-case:`controllers/date_picker_controller.js`、`controllers/list-item-controller.js`)。
+
+
+ 原文
+
+Always use camelCase for method and property names in a controller class.
+
+When an identifier is composed of more than one word, write the words in kebab-case (i.e., by using dashes: date-picker, list-item).
+
+In filenames, separate multiple words using either underscores or dashes (snake_case or kebab-case: controllers/date_picker_controller.js, controllers/list-item-controller.js).
+
+
+## コントローラの登録
+
+Stimulus for Railsをimport-maps と一緒に使うか、Webpackで`@hotwired/stimulus-webpack-helpers`パッケージを使うと、アプリケーションは自動的に上記の規約に従ってコントローラクラスをロードして登録します。
+
+もしそれらを使わない場合、各コントローラクラスを手動で読み込んで登録する必要があります。
+
+
+ 原文
+If you use Stimulus for Rails with an import map or Webpack together with the @hotwired/stimulus-webpack-helpers package, your application will automatically load and register controller classes following the conventions above.
+
+If not, your application must manually load and register each controller class.
+
+
+### コントローラの手動登録
+
+コントローラクラスを手動で登録するには、まずクラスをインポートし、`application`オブジェクトの`register`メソッドを呼び出します:
+
+```javascript
+import ReferenceController from "./controllers/reference_controller"
+
+application.register("reference", ReferenceController)
+```
+
+モジュールとしてインポートする代わりに、インラインでコントローラクラスを登録することもできます:
+
+```javascript
+import { Controller } from "@hotwired/stimulus"
+
+application.register("reference", class extends Controller {
+ // …
+})
+```
+
+
+ 原文
+To manually register a controller class with an identifier, first import the class, then call the Application#register method on your application object:
+
+```javascript
+import ReferenceController from "./controllers/reference_controller"
+
+application.register("reference", ReferenceController)
+```
+
+You can also register a controller class inline instead of importing it from a module:
+
+```javascript
+import { Controller } from "@hotwired/stimulus"
+
+application.register("reference", class extends Controller {
+ // …
+})
+```
+
+
+### 環境要因に基づくコントローラの登録キャンセル
+
+特定の環境要因 (たとえば指定したユーザーエージェントなど) が満たされた場合にのみコントローラを登録したい場合は、 `shouldLoad`(静的)ゲッターを上書きすることで可能です:
+
+```javascript
+class UnloadableController extends ApplicationController {
+ static get shouldLoad() {
+ return false
+ }
+}
+
+// This controller will not be loaded
+application.register("unloadable", UnloadableController)
+```
+
+
+ 原文
+
+If you only want a controller registered and loaded if certain environmental factors are met – such a given user agent – you can overwrite the static shouldLoad method:
+
+```javascript
+class UnloadableController extends ApplicationController {
+ static get shouldLoad() {
+ return false
+ }
+}
+
+// This controller will not be loaded
+application.register("unloadable", UnloadableController)
+```
+
+
+### コントローラ登録時に発火するコールバック
+
+コントローラが登録された直後に何らかの動作をさせたい場合は、`afterLoad`(静的)メソッドを追加します:
+
+```javascript
+class SpinnerButton extends Controller {
+ static legacySelector = ".legacy-spinner-button"
+
+ static afterLoad(identifier, application) {
+ // アプリケーションインスタンスにアクセスして、'data-controller' に当たる属性名を読み込む。
+ const { controllerAttribute } = application.schema
+
+ // レガシーボタンに本コントローラがアタッチされるように属性をセットする
+ const updateLegacySpinners = () => {
+ document.querySelector(this.legacySelector).forEach((element) => {
+ element.setAttribute(controllerAttribute, identifier)
+ })
+ }
+
+ // このafterLoadメソッドはこのとローラが登録されるとすぐに呼び出されるので、
+ // DOMはまだロードされていないかもしれないのでそこをケアする
+ if (document.readyState == "loading") {
+ document.addEventListener("DOMContentLoaded", updateLegacySpinners)
+ } else {
+ updateLegacySpinners()
+ }
+ }
+}
+
+// このコントローラは、従来のスピナーボタンを変更し、本コントローラを適用させます。
+application.register("spinner-button", SpinnerButton)
+```
+
+`afterLoad`メソッドはコントローラが登録されるとすぐに呼び出されます。 この関数には、2つの引数(コントローラの登録時に指定された識別子と登録先の`Application`のインスタンス)が渡ります。 実行時のコンテキストは元のコントローラクラスです。
+
+
+ 原文
+
+If you want to trigger some behaviour once a controller has been registered you can add a static afterLoad method:
+
+```javascript
+class SpinnerButton extends Controller {
+ static legacySelector = ".legacy-spinner-button"
+
+ static afterLoad(identifier, application) {
+ // use the application instance to read the configured 'data-controller' attribute
+ const { controllerAttribute } = application.schema
+
+ // update any legacy buttons with the controller's registered identifier
+ const updateLegacySpinners = () => {
+ document.querySelector(this.legacySelector).forEach((element) => {
+ element.setAttribute(controllerAttribute, identifier)
+ })
+ }
+
+ // called as soon as registered so DOM may not have loaded yet
+ if (document.readyState == "loading") {
+ document.addEventListener("DOMContentLoaded", updateLegacySpinners)
+ } else {
+ updateLegacySpinners()
+ }
+ }
+}
+
+// This controller will update any legacy spinner buttons to use the controller
+application.register("spinner-button", SpinnerButton)
+```
+
+The afterLoad method will get called as soon as the controller has been registered, even if no controlled elements exist in the DOM. The function will be called bound to the original controller constructor along with two arguments; the identifier that was used when registering the controller and the Stimulus application instance.
+
+
+
+## イベントを使ったコントローラ間の連携
+
+コントローラ間で連携を行う必要がある場合はイベントを使用します。 コントローラクラスにはカスタムイベントを発生させるための`dispatch`という便利なメソッドが用意されています。 このメソッドは`eventName`を第1引数にとりますが、実際のイベント名は、プレフィックスとして自動的にコントローラの識別子をコロンで区切りで挿入したものになります。 ペイロードは`detail`に保持することができます。 これは次のように動作します:
+
+```javascript
+class ClipboardController extends Controller {
+ static targets = [ "source" ]
+
+ copy() {
+ this.dispatch("copy", { detail: { content: this.sourceTarget.value } })
+ navigator.clipboard.writeText(this.sourceTarget.value)
+ }
+}
+```
+
+このイベントは、次のようにして別のコントローラーのアクションにルーティングできます。
+
+```html
+
+ PIN:
+
+
+```
+
+この指定により`Clipboard#copy`アクションが呼び出されると、`Effects#flash`アクションも呼び出されるようになります。
+
+```javascript
+class EffectsController extends Controller {
+ flash({ detail: { content } }) {
+ console.log(content) // 1234
+ }
+}
+```
+
+2つのコントローラが同じHTML要素に属していない場合は、イベント購読側のコントローラの要素に`data-action`属性を追加する必要があります。 また、購読側コントローラの要素がイベント発行側コントローラの要素の親 (または同じ) でない場合は、イベント名の後に`@window`を追加する必要があります。
+
+```html
+
+```
+
+`dispatch`は、第2引数として以下のような追加オプションを受け付ける:
+
+| option | デフォルト値 | ノート |
+|---|---|---|
+| `detail` | `{}` (空オブジェクト) | [CustomEvent.detail](https://developer.mozilla.org/ja/docs/Web/API/CustomEvent/detail)を参照 |
+| `target` | `this.element` | [See Event.target](https://developer.mozilla.org/ja/docs/Web/API/Event/target)を参照 |
+| `prefix` | `this.identifier` | プレフィックスがfalseyの場合(`null`や`false`など)は`eventName`がそのまま使用される。文字列を指定した場合は、`eventName`の前に指定した文字列とコロンが付加されます。 |
+| `bubbles` | `true` | [Event.bubbles](https://developer.mozilla.org/ja/docs/Web/API/Event/bubbles)を参照 |
+| `cancelable` | `true` | [Event.cancelable](https://developer.mozilla.org/ja/docs/Web/API/Event/cancelable)を参照 |
+
+`dispatch`は生成された`CustomEvent`を返すので、これを使って以下のように他のリスナからイベントをキャンセルさせることができます:
+
+```javascript
+class ClipboardController extends Controller {
+ static targets = [ "source" ]
+
+ copy() {
+ const event = this.dispatch("copy", { cancelable: true })
+ if (event.defaultPrevented) return
+ navigator.clipboard.writeText(this.sourceTarget.value)
+ }
+}
+```
+
+```javascript
+class EffectsController extends Controller {
+ flash(event) {
+ // ディスパッチされたイベントによって引き起こされるデフォルトの振る舞いを防ぎます
+ event.preventDefault()
+ }
+}
+```
+
+
+ 原文
+
+If you need controllers to communicate with each other, you should use events. The Controller class has a convenience method called dispatch that makes this easier. It takes an eventName as the first argument, which is then automatically prefixed with the name of the controller separated by a colon. The payload is held in detail. It works like this:
+
+```javascript
+class ClipboardController extends Controller {
+ static targets = [ "source" ]
+
+ copy() {
+ this.dispatch("copy", { detail: { content: this.sourceTarget.value } })
+ navigator.clipboard.writeText(this.sourceTarget.value)
+ }
+}
+```
+
+And this event can then be routed to an action on another controller:
+
+```html
+
+ PIN:
+
+
+```
+
+So when the Clipboard#copy action is invoked, the Effects#flash action will be too:
+
+```javascript
+class EffectsController extends Controller {
+ flash({ detail: { content } }) {
+ console.log(content) // 1234
+ }
+}
+```
+
+If the two controllers don’t belong to the same HTML element, the data-action attribute needs to be added to the receiving controller’s element. And if the receiving controller’s element is not a parent (or same) of the emitting controller’s element, you need to add @window to the event:
+
+```html
+
+```
+
+dispatch accepts additional options as the second parameter as follows:
+
+| option | default | notes |
+|---|---|
+| detail | {} empty object | See CustomEvent.detail |
+| target | this.element | See Event.target |
+| prefix | this.identifier | If the prefix is falsey (e.g. null or false), only the eventName will be used. If you provide a string value the eventName will be prepended with the provided string and a colon. |
+| bubbles | true | See Event.bubbles |
+| cancelable | true | See Event.cancelable |
+
+dispatch will return the generated CustomEvent, you can use this to provide a way for the event to be cancelled by any other listeners as follows:
+
+```javascript
+class ClipboardController extends Controller {
+ static targets = [ "source" ]
+
+ copy() {
+ const event = this.dispatch("copy", { cancelable: true })
+ if (event.defaultPrevented) return
+ navigator.clipboard.writeText(this.sourceTarget.value)
+ }
+}
+```
+
+```javascript
+class EffectsController extends Controller {
+ flash(event) {
+ // this will prevent the default behaviour as determined by the dispatched event
+ event.preventDefault()
+ }
+}
+```
+
+
+## コントローラから別のコントローラを直接呼び出す
+
+何らかの理由でコントローラ間の通信にイベントを使用できない場合は、`application`オブジェクトの`getControllerForElementAndIdentifier`メソッドを使うことができます。 これは、イベントを使用する一般的な方法では解決できないような特殊な問題がある場合にのみ使用すべきです:
+
+```javascript
+class MyController extends Controller {
+ static targets = [ "other" ]
+
+ copy() {
+ const otherController = this.application.getControllerForElementAndIdentifier(this.otherTarget, 'other')
+ otherController.otherMethod()
+ }
+}
+```
+
+
+ 原文
+If for some reason it is not possible to use events to communicate between controllers, you can reach a controller instance via the getControllerForElementAndIdentifier method from the application. This should only be used if you have a unique problem that cannot be solved through the more general way of using events, but if you must, this is how:
+
+```javascript
+class MyController extends Controller {
+ static targets = [ "other" ]
+
+ copy() {
+ const otherController = this.application.getControllerForElementAndIdentifier(this.otherTarget, 'other')
+ otherController.otherMethod()
+ }
+}
+```
+
diff --git a/stimulus/reference/css_classes.md b/stimulus/reference/css_classes.md
new file mode 100644
index 00000000..fefc2819
--- /dev/null
+++ b/stimulus/reference/css_classes.md
@@ -0,0 +1,268 @@
+---
+title: CSS Classes
+description: CSSクラスを論理名でコントローラから参照できるようにする"
+order: 6
+---
+
+# CSS Classes
+
+HTMLの _CSSクラス_ は、`class`属性を使用して、要素に適用されるスタイルのセットを定義します。
+
+CSSクラスは、プログラムでスタイルを変更したりアニメーションを再生したりするのに便利です。 例えば、Stimulusコントローラで、バックグラウンドでなんらかの操作を実行しているときに読み込み中のUIを表示させるために`loading`を要素につけるといったこともできます。
+
+```html
+
+```
+
+コントローラ識別子と論理名を`data-[identifier]-[logical-name]-class`の形式で結合して、classデータ属性を作ります。 この属性の値には、単一のCSSクラス名または複数のクラス名のリストを指定することができます。
+
+**注:** classデータ属性は、`data-controller`属性と同じ要素に指定する必要があります。
+
+論理名に複数のCSSクラスを指定する場合は、クラスをスペースで区切ります。
+
+```html
+
+```
+
+
+ 原文
+
+The logical names defined in the controller's `static classes` array map to _CSS class attributes_ on the controller's element.
+
+```html
+
+```
+
+Construct a CSS class attribute by joining together the controller identifier and logical name in the format `data-[identifier]-[logical-name]-class`. The attribute's value can be a single CSS class name or a list of multiple class names.
+
+**Note:** CSS class attributes must be specified on the same element as the `data-controller` attribute.
+
+If you want to specify multiple CSS classes for a logical name, separate the classes with spaces:
+
+```html
+
+```
+
+
+## プロパティ
+
+`static classes`配列で定義された論理名ごとに、Stimulusは次のプロパティをコントローラに追加します。
+
+Kind | Name | Value
+-------- | ---------------------------- | -----
+単数 | `this.[logicalName]Class` | `logicalName`に対応するclassデータ属性の値
+複数形 | `this.[logicalName]Classes` | 対応するclassデータ属性に含まれる全てのクラスをスペースで分割した配列
+存在有無 | `this.has[LogicalName]Class` | classデータ属性が存在するかどうかを示すbool値
+
+
これらのプロパティと [DOM classList API](https://developer.mozilla.org/ja/docs/Web/API/Element/classList) の`add() `および`remove() `メソッドを使用して要素にCSSクラスを適用します。
+
+たとえば、(ajax通信などの)結果をフェッチする前に`search`コントローラの要素に読み込みインジケータを表示するには、次のように`loadResults`関数を実装します。
+
+```js
+export default class extends Controller {
+ static classes = [ "loading" ]
+
+ loadResults() {
+ this.element.classList.add(this.loadingClass)
+
+ fetch(/* … */)
+ }
+}
+```
+
+classデータ属性にクラス名のリストが含まれている場合、単数系のcss-classプロパティ(`loadingClass`)はリスト内の最初のクラスを返します。
+
+classデータ属性に記述された全てのクラス名に配列としてアクセスするには、複数形のcss-classプロパティを使用します。 これを [スプレッド構文](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax) と組み合わせると、複数のクラスを一度に適用することができます。
+
+```js
+export default class extends Controller {
+ static classes = [ "loading" ]
+
+ loadResults() {
+ this.element.classList.add(...this.loadingClasses)
+
+ fetch(/* … */)
+ }
+}
+```
+
+**注:** 一致するclassデータ属性が存在しない場合にcss-classプロパティにアクセスしようとすると、Stimulusはエラーをスローします。
+
+
+ 原文
+For each logical name defined in the `static classes` array, Stimulus adds the following _CSS class properties_ to your controller:
+
+Kind | Name | Value
+----------- | ---------------------------- | -----
+Singular | `this.[logicalName]Class` | The value of the CSS class attribute corresponding to `logicalName`
+Plural | `this.[logicalName]Classes` | An array of all classes in the corresponding CSS class attribute, split by spaces
+Existential | `this.has[LogicalName]Class` | A boolean indicating whether or not the CSS class attribute is present
+
+
Use these properties to apply CSS classes to elements with the `add()` and `remove()` methods of the [DOM `classList` API](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList).
+
+For example, to display a loading indicator on the `search` controller's element before fetching results, you might implement the `loadResults` action like so:
+
+```js
+export default class extends Controller {
+ static classes = [ "loading" ]
+
+ loadResults() {
+ this.element.classList.add(this.loadingClass)
+
+ fetch(/* … */)
+ }
+}
+```
+
+If a CSS class attribute contains a list of class names, its singular CSS class property returns the first class in the list.
+
+Use the plural CSS class property to access all class names as an array. Combine this with [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) to apply multiple classes at once:
+
+```js
+export default class extends Controller {
+ static classes = [ "loading" ]
+
+ loadResults() {
+ this.element.classList.add(...this.loadingClasses)
+
+ fetch(/* … */)
+ }
+}
+```
+
+**Note:** Stimulus will throw an error if you attempt to access a CSS class property when a matching CSS class attribute is not present.
+
+
+
+## 命名規則
+
+`static classes`定義で論理名を指定する際はキャメルケースを使用します。 論理名はキャメルケースのままcss-classプロパティにマップされます。
+
+```js
+export default class extends Controller {
+ static classes = [ "loading", "noResults" ]
+
+ loadResults() {
+ // …
+ if (results.length == 0) {
+ this.element.classList.add(this.noResultsClass)
+ }
+ }
+}
+```
+
+HTMLでは、classデータ属性をケバブケースで記述します。
+
+```html
+