From 6f6b9078fab328ba592822484426e11272d544b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=A8=E3=82=93=E3=81=A8=E3=82=93=E3=81=BC?= <70003919+KaitoMuraoka@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:47:49 +0900 Subject: [PATCH] Translate Leaf to Japanese (#1005) [Leaf content](https://docs.vapor.codes/ja/leaf/overview/) translated into Japanese - getting-started.md - overview.md - custom-tags.md --------- Co-authored-by: Tim Condon <0xTim@users.noreply.github.com> --- docs/leaf/custom-tags.ja.md | 128 ++++++++++++++ docs/leaf/getting-started.ja.md | 95 +++++++++++ docs/leaf/overview.ja.md | 291 ++++++++++++++++++++++++++++++++ 3 files changed, 514 insertions(+) create mode 100644 docs/leaf/custom-tags.ja.md create mode 100644 docs/leaf/getting-started.ja.md create mode 100644 docs/leaf/overview.ja.md diff --git a/docs/leaf/custom-tags.ja.md b/docs/leaf/custom-tags.ja.md new file mode 100644 index 00000000..b2c0f1c6 --- /dev/null +++ b/docs/leaf/custom-tags.ja.md @@ -0,0 +1,128 @@ +# カスタムタグ + +[`LeafTag`](https://api.vapor.codes/leafkit/documentation/leafkit/leaftag) プロトコルを使用して、カスタム Leaf タグを作成することができます。 + +これを実際に試してみるために、現在のタイムスタンプを表示するカスタムタグ `#now` を作成してみましょう。このタグは、日付形式を指定するためのオプションのパラメータもサポートします。 + +!!! tip + もしカスタムタグが HTML をレンダリングする場合は、HTML がエスケープされないように、`UnsafeUnescapedLeafTag` に準拠させる必要があります。ユーザー入力のチェックやサニタイズを忘れないようにしましょう。 + +## `LeafTag` + +まず、`NowTag` というクラスを作成し、`LeafTag` に準拠させます。 + +```swift +struct NowTag: LeafTag { + func render(_ ctx: LeafContext) throws -> LeafData { + ... + } +} +``` + +次に、`render(_:)` メソッドを実装します。このメソッドに渡される `LeafContext` は、必要なすべての情報を持っています。 + +```swift +enum NowTagError: Error { + case invalidFormatParameter + case tooManyParameters +} + +struct NowTag: LeafTag { + func render(_ ctx: LeafContext) throws -> LeafData { + let formatter = DateFormatter() + switch ctx.parameters.count { + case 0: formatter.dateFormat = "yyyy-MM-dd HH:mm:ss" + case 1: + guard let string = ctx.parameters[0].string else { + throw NowTagError.invalidFormatParameter + } + + formatter.dateFormat = string + default: + throw NowTagError.tooManyParameters + } + + let dateAsString = formatter.string(from: Date()) + return LeafData.string(dateAsString) + } +} +``` + +## タグの設定 + +`NowTag` を実装したので、Leaf にそれを伝えるだけです。このようにして、たとえ別のパッケージで定義されたタグでも追加することができます。通常、これを `configure.swift` で行います: + +```swift +app.leaf.tags["now"] = NowTag() +``` + +これで完了です!Leaf でカスタムタグを使用できるようになりました。 + +```leaf +The time is #now() +``` + +## コンテキストプロパティ + +`LeafContext` には、重要なプロパティが 2 つあります。それが `parameters` と `data` です。この 2 つで必要な情報はすべて揃っています。 + +- `parameters`: タグのパラメータを含む配列です +- `data`: コンテキストとして `render(_:_:)` に渡されたビューのデータを含む辞書です + +### Hello タグによる実例 + +これを理解するために、両方のプロパティを使ったシンプルな hello タグを実装してみましょう。 + +#### parameters の使用 + +nameの値が提供される、1つ目のパラメータにアクセスできます + +```swift +enum HelloTagError: Error { + case missingNameParameter +} + +struct HelloTag: UnsafeUnescapedLeafTag { + func render(_ ctx: LeafContext) throws -> LeafData { + guard let name = ctx.parameters[0].string else { + throw HelloTagError.missingNameParameter + } + + return LeafData.string("
Hello \(name)
") + } +} +``` + +```leaf +#hello("John") +``` + +#### data の使用 + +data プロパティの中の "name" キーを使って名前の値にアクセスします。 + +```swift +enum HelloTagError: Error { + case nameNotFound +} + +struct HelloTag: UnsafeUnescapedLeafTag { + func render(_ ctx: LeafContext) throws -> LeafData { + guard let name = ctx.data["name"]?.string else { + throw HelloTagError.nameNotFound + } + + return LeafData.string("Hello \(name)
") + } +} +``` + +```leaf +#hello() +``` + +_Controller_: + +```swift +return try await req.view.render("home", ["name": "John"]) +``` diff --git a/docs/leaf/getting-started.ja.md b/docs/leaf/getting-started.ja.md new file mode 100644 index 00000000..85e8b369 --- /dev/null +++ b/docs/leaf/getting-started.ja.md @@ -0,0 +1,95 @@ +# Leaf + +Leaf は、Swift にインスパイアされた構文を持つ強力なテンプレート言語です。これを使って、フロントエンドのウェブサイト向けに動的な HTML ページを生成したり、API から送信するリッチなメールを生成したりできます。 + +## Package + +Leaf を使用する最初のステップは、プロジェクトの SPM パッケージマニフェストファイルに依存関係として追加することです。 + +```swift +// swift-tools-version:5.8 +import PackageDescription + +let package = Package( + name: "MyApp", + platforms: [ + .macOS(.v10_15) + ], + dependencies: [ + /// Any other dependencies ... + .package(url: "https://github.com/vapor/leaf.git", from: "4.4.0"), + ], + targets: [ + .target(name: "App", dependencies: [ + .product(name: "Leaf", package: "leaf"), + // Any other dependencies + ]), + // Other targets + ] +) +``` + +## 設定 + +パッケージをプロジェクトに追加したら、Vapor を設定してそれを使用するように構成します。これは通常、[`configure.swift`](../getting-started/folder-structure.md#configureswift) で行います。 + +```swift +import Leaf + +app.views.use(.leaf) +``` + +これにより、コード内で `req.view` を呼び出すと、Vapor が `LeafRenderer` を使用するように指示します。 + +!!! note + Leaf には、ページをレンダリングするための内部キャッシュがあります。`Application` の環境が `.development` に設定されている場合、このキャッシュは無効になり、テンプレートへの変更が即座に反映されます。`.production` やその他の環境では、キャッシュがデフォルトで有効になっており、テンプレートに加えた変更はアプリケーションを再起動するまで反映されません。 + +!!! warning + Xcode から実行する際に Leaf がテンプレートを見つけられるようにするためには、 Xcode ワークスペースの [custom working directory](../getting-started/xcode.md#_1) を設定する必要があります。 +## フォルダ構成 + +Leaf を設定したら、`.leaf` ファイルを格納するための `Views` フォルダを用意する必要があります。デフォルトでは、Leaf はプロジェクトのルートに対して `./Resources/Views` というフォルダを要求します。 + +JavaScript や CSS ファイルを提供する予定がある場合は、Vapor の [`FileMiddleware`](https://api.vapor.codes/vapor/documentation/vapor/filemiddleware) を有効にして、 `/Public` フォルダからファイルを提供できるようにすることも可能です。 + +``` +VaporApp +├── Package.swift +├── Resources +│ ├── Views +│ │ └── hello.leaf +├── Public +│ ├── images (images resources) +│ ├── styles (css resources) +└── Sources + └── ... +``` + +## Viewのレンダリング + +Leaf が設定できたので、最初のテンプレートをレンダリングしてみましょう。`Resources/Views` フォルダ内に、次の内容で `hello.leaf` という新しいファイルを作成します。 + +```leaf +Hello, #(name)! +``` + +!!! tip + もし、コードエディタとして VSCode を使用している場合、シンタックスハイライトを有効にするために、Leaf 拡張機能をインストールすることをお勧めします:[Leaf HTML](https://marketplace.visualstudio.com/items?itemName=Francisco.html-leaf) + +次に、View をレンダリングするルートを登録します。(通常は、`routes.swift` やコントローラで行います) + +```swift +app.get("hello") { req -> EventLoopFuture#(number)
+#endfor +``` + +## 使用例 + +以下は、Leaf の一般的な使用例です。 + +### 条件 + +Leaf は、`#if` タグを使用してさまざまな条件を評価できます。例えば、変数を提供すると、その変数がコンテキストに存在するかチェックします: + +```leaf +#if(title): + The title is #(title) +#else: + No title was provided. +#endif +``` + +また、比較を行うこともできます。例: + +```leaf +#if(title == "Welcome"): + This is a friendly web page. +#else: + No strangers allowed! +#endif +``` + +別のタグを条件の一部として使用したい場合は、内側のタグの `#` を省略する必要があります。例: + +```leaf +#if(count(users) > 0): + You have users! +#else: + There are no users yet :( +#endif +``` + +また、`#elseif` ステートメントを使用することもできます: + +```leaf +#if(title == "Welcome"): + Hello new user! +#elseif(title == "Welcome back!"): + Hello old user +#else: + Unexpected page! +#endif +``` + +### ループ + +アイテムの配列を提供すると、Leaf はそれをループし、 `#for` タグを使用して各アイテムを個別に操作できます。 + +例えば、Swift コードを更新して、惑星のリストを提供することができます: + +```swift +struct SolarSystem: Codable { + let planets = ["Venus", "Earth", "Mars"] +} + +return req.view.render("solarSystem", SolarSystem()) +``` + +その後、Leaf で次のようにループを行うことができます: + +```leaf +Planets: +Welcome to Vapor!
+ #endexport +#endextend +``` + +ここでは、`#export` を使用して HTML を保存し、現在拡張しているテンプレートで利用できるようにしています。その後、`master.leaf` をレンダリングし、Swift から渡された他のコンテキスト変数と共にエクスポートされたデータを使用します。例えば、`master.leaf` は次のようになります: + +```leaf + + +Welcome to Vapor!
+ +``` + +### その他のタグ + +#### `#count` + +`#count` タグは、配列内のアイテム数を返します。例: + +```leaf +Your search matched #count(matches) pages. +``` + +#### `#lowercased` + +`#lowercased` タグは、文字列内のすべての文字を小文字に変換します。 + +```leaf +#lowercased(name) +``` + +#### `#uppercased` + +`#uppercased` タグは、文字列内のすべての文字を大文字に変換します。 + +```leaf +#uppercased(name) +``` + +#### `#capitalized` + +`#capitalized` タグは、文字列の各単語の最初の文字を大文字にし、他の文字を小文字に変換します。詳細は [`String.capitalized`](https://developer.apple.com/documentation/foundation/nsstring/1416784-capitalized)をご覧ください。 + +```leaf +#capitalized(name) +``` + +#### `#contains` + +`#contains` タグは、配列と値を2つのパラメータとして受け取り、パラメータ1の配列にパラメータ2の値が含まれているかどうかを返します。 + +```leaf +#if(contains(planets, "Earth")): + Earth is here! +#else: + Earth is not in this array. +#endif +``` + +#### `#date` + +`#date` タグは、日付を読みやすい文字列にフォーマットします。デフォルトでは ISO8601 フォーマットを使用します。 + +```swift +render(..., ["now": Date()]) +``` + +```leaf +The time is #date(now) +``` + +カスタム日付フォーマット文字列を2番目の引数として渡すこともできます。詳細は Swift の [`DateFormatter`](https://developer.apple.com/documentation/foundation/dateformatter) をご覧ください。 + +```leaf +The date is #date(now, "yyyy-MM-dd") +``` + +日付フォーマッターのタイムゾーン ID を3番目の引数として渡すこともできます。詳細は Swift の [`DateFormatter.timeZone`](https://developer.apple.com/documentation/foundation/dateformatter/1411406-timezone) または [`TimeZone`](https://developer.apple.com/documentation/foundation/timezone) をご覧ください。 + +```leaf +The date is #date(now, "yyyy-MM-dd", "America/New_York") +``` + +#### `#unsafeHTML` + +`#unsafeHTML` タグは、変数タグ(例: `#(variable)`) のように動作します。しかし、`variable` が含む可能性のある HTML はエスケープしません。 + +```leaf +The time is #unsafeHTML(styledTitle) +``` + +!!! note + このタグを使用する際は、提供する変数がユーザーを XSS 攻撃に晒さないように注意する必要があります。 + +#### `#dumpContext` + +`dumpContext` タグは、コンテキスト全体を人間が読める形式でレンダリングします。このタグを使用して、現在のレンダリングに提供されているコンテキストをデバッグします。 + +```leaf +Hello, world! +#dumpContext +``` \ No newline at end of file