```console
-$ pip install uvicorn[standard]
+$ pip install "uvicorn[standard]"
---> 100%
```
-## Example
+## Exemple
-### Create it
+### Créez
-* Create a file `main.py` with:
+* Créez un fichier `main.py` avec :
```Python
-from typing import Optional
+from typing import Union
from fastapi import FastAPI
@@ -162,17 +170,17 @@ def read_root():
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: Optional[str] = None):
+def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [28720]
+INFO: Started server process [28722]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [28720]
+INFO: Started server process [28722]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+
```console
-$ pip install uvicorn[standard]
+$ pip install "fastapi[standard]"
---> 100%
```
-## Example
+**Catatan**: Pastikan anda menulis `"fastapi[standard]"` dengan tanda petik untuk memastikan bisa digunakan di semua *terminal*.
+
+## Contoh
-### Create it
+### Buat app
-* Create a file `main.py` with:
+* Buat file `main.py` dengan:
```Python
-from typing import Optional
+from typing import Union
from fastapi import FastAPI
@@ -162,17 +161,17 @@ def read_root():
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: Optional[str] = None):
+def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
```console
-$ uvicorn main:app --reload
-
+$ fastapi dev main.py
+
+ ╭────────── FastAPI CLI - Development mode ───────────╮
+ │ │
+ │ Serving at: http://127.0.0.1:8000 │
+ │ │
+ │ API docs: http://127.0.0.1:8000/docs │
+ │ │
+ │ Running in development mode, for production use: │
+ │ │
+ │ fastapi run │
+ │ │
+ ╰─────────────────────────────────────────────────────╯
+
+INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
-INFO: Started reloader process [28720]
-INFO: Started server process [28722]
+INFO: Started reloader process [2248755] using WatchFiles
+INFO: Started server process [2248757]
INFO: Waiting for application startup.
INFO: Application startup complete.
```
@@ -214,57 +226,57 @@ INFO: Application startup complete.
-
- ```console
- $ which pip
-
- some/directory/fastapi/env/bin/pip
- ```
-
-
-
-=== "Windows PowerShell"
-
-
-
- ```console
- $ Get-Command pip
-
- some/directory/fastapi/env/bin/pip
- ```
-
-
-
-`env/bin/pip`に`pip`バイナリが表示される場合は、正常に機能しています。🎉
-
-
-!!! tip "豆知識"
- この環境で`pip`を使って新しいパッケージをインストールするたびに、仮想環境を再度有効化します。
-
- これにより、そのパッケージによってインストールされたターミナルのプログラム (`flit`など) を使用する場合、ローカル環境のものを使用し、グローバルにインストールされたものは使用されなくなります。
-
-### Flit
-
-**FastAPI**は
-
- ```console
- $ flit install --deps develop --symlink
-
- ---> 100%
- ```
-
-
-
-=== "Windows"
-
- Windowsユーザーは、`--symlink`のかわりに`--pth-file`を使用します:
-
-
-
- ```console
- $ flit install --deps develop --pth-file
-
- ---> 100%
- ```
-
-
-
-これで、すべての依存関係とFastAPIを、ローカル環境にインストールします。
-
-#### ローカル環境でFastAPIを使う
-
-FastAPIをインポートして使用するPythonファイルを作成し、ローカル環境で実行すると、ローカルのFastAPIソースコードが使用されます。
-
-そして、`--symlink` (Windowsでは` --pth-file`) でインストールされているローカルのFastAPIソースコードを更新した場合、そのPythonファイルを再度実行すると、更新したばかりの新しいバージョンのFastAPIが使用されます。
-
-これにより、ローカルバージョンを「インストール」しなくても、すべての変更をテストできます。
-
-### コードの整形
-
-すべてのコードを整形してクリーンにするスクリプトがあります:
-
-
-
-```console
-$ typer --install-completion
-
-zsh completion installed in /home/user/.bashrc.
-Completion will take effect once you restart the terminal.
-```
-
-
-
-### アプリとドキュメントを同時に
-
-以下の様にサンプルを実行すると:
-
-
-
-```console
-// コマンド"live"を使用し、言語コードをCLIに引数で渡します。
-$ python ./scripts/docs.py live es
-
-[INFO] Serving on http://127.0.0.1:8008
-[INFO] Start watching changes
-[INFO] Start detecting changes
-```
-
-
-
-これで
-
-```console
-// コマンド「new-lang」を使用して、言語コードをCLIに引数で渡します
-$ python ./scripts/docs.py new-lang ht
-
-Successfully initialized: docs/ht
-Updating ht
-Updating en
-```
-
-
-
-これで、新しく作成された`docs/ht/`ディレクトリをコードエディターから確認できます。
-
-!!! tip "豆知識"
- 翻訳を追加する前に、これだけで最初のプルリクエストを作成し、新しい言語の設定をセットアップします。
-
- そうすることで、最初のページで作業している間、誰かの他のページの作業を助けることができます。 🚀
-
-まず、メインページの`docs/ht/index.md`を翻訳します。
-
-その後、「既存の言語」で、さきほどの手順を続行してください。
-
-##### まだサポートされていない新しい言語
-
-ライブサーバースクリプトを実行するときに、サポートされていない言語に関するエラーが発生した場合は、次のように表示されます:
-
-```
- raise TemplateNotFound(template)
-jinja2.exceptions.TemplateNotFound: partials/language/xx.html
-```
-
-これは、テーマがその言語をサポートしていないことを意味します (この場合は、`xx`の2文字の偽のコード) 。
-
-ただし、心配しないでください。テーマ言語を英語に設定して、ドキュメントの内容を翻訳できます。
-
-その必要がある場合は、新しい言語の`mkdocs.yml`を次のように編集してください:
-
-```YAML hl_lines="5"
-site_name: FastAPI
-# More stuff
-theme:
- # More stuff
- language: xx
-```
-
-その言語を`xx` (あなたの言語コード) から`en`に変更します。
-
-その後、ライブサーバーを再起動します。
-
-#### 結果のプレビュー
-
-`./scripts/docs.py`のスクリプトを`live`コマンドで使用すると、現在の言語で利用可能なファイルと翻訳のみが表示されます。
-
-しかし一度実行したら、オンラインで表示されるのと同じように、すべてをテストできます。
-
-このために、まずすべてのドキュメントをビルドします:
-
-
-
-```console
-// 「build-all」コマンドは少し時間がかかります。
-$ python ./scripts/docs.py build-all
-
-Updating es
-Updating en
-Building docs for: en
-Building docs for: es
-Successfully built docs for: es
-Copying en index.md to README.md
-```
-
-
-
-これで、言語ごとにすべてのドキュメントが`./docs_build/`に作成されます。
-
-これには、翻訳が欠落しているファイルを追加することと、「このファイルにはまだ翻訳がない」というメモが含まれます。ただし、そのディレクトリで何もする必要はありません。
-
-次に、言語ごとにこれらすべての個別のMkDocsサイトを構築し、それらを組み合わせて、`./site/`に最終結果を出力します。
-
-これは、コマンド`serve`で提供できます:
-
-
-
-```console
-// 「build-all」コマンドの実行の後に、「serve」コマンドを使います
-$ python ./scripts/docs.py serve
-
-Warning: this is a very simple server. For development, use mkdocs serve instead.
-This is here only to preview a site with translations already built.
-Make sure you run the build-all command first.
-Serving at: http://127.0.0.1:8008
-```
-
-
-
-## テスト
-
-すべてのコードをテストし、HTMLでカバレッジレポートを生成するためにローカルで実行できるスクリプトがあります:
-
-
-
- ```console
- $ curl -fsSL https://get.deta.dev/cli.sh | sh
- ```
-
-
-
-=== "Windows PowerShell"
-
-
-
- ```console
- $ iwr https://get.deta.dev/cli.ps1 -useb | iex
- ```
-
-
-
-インストールしたら、インストールした CLI を有効にするために新たなターミナルを開いてください。
-
-新たなターミナル上で、正しくインストールされたか確認します:
-
-
-
-```console
-$ deta --help
-
-Deta command line interface for managing deta micros.
-Complete documentation available at https://docs.deta.sh
-
-Usage:
- deta [flags]
- deta [command]
-
-Available Commands:
- auth Change auth settings for a deta micro
-
-...
-```
-
-
-
-!!! tip "豆知識"
- CLI のインストールに問題が発生した場合は、
-
-```console
-$ deta login
-
-Please, log in from the web page. Waiting..
-Logged in successfully.
-```
-
-
-
-自動的にウェブブラウザが開いて、認証処理が行われます。
-
-## Deta でデプロイ
-
-次に、アプリケーションを Deta CLIでデプロイしましょう:
-
-
-
-```console
-$ deta new
-
-Successfully created a new micro
-
-// Notice the "endpoint" 🔍
-
-{
- "name": "fastapideta",
- "runtime": "python3.7",
- "endpoint": "https://qltnci.deta.dev",
- "visor": "enabled",
- "http_auth": "enabled"
-}
-
-Adding dependencies...
-
-
----> 100%
-
-
-Successfully installed fastapi-0.61.1 pydantic-1.7.2 starlette-0.13.6
-```
-
-
-
-次のようなJSONメッセージが表示されます:
-
-```JSON hl_lines="4"
-{
- "name": "fastapideta",
- "runtime": "python3.7",
- "endpoint": "https://qltnci.deta.dev",
- "visor": "enabled",
- "http_auth": "enabled"
-}
-```
-
-!!! tip "豆知識"
- あなたのデプロイでは異なる `"endpoint"` URLが表示されるでしょう。
-
-## 確認
-
-それでは、`endpoint` URLをブラウザで開いてみましょう。上記の例では `https://qltnci.deta.dev` ですが、あなたのURLは異なるはずです。
-
-FastAPIアプリから返ってきたJSONレスポンスが表示されます:
-
-```JSON
-{
- "Hello": "World"
-}
-```
-
-そして `/docs` へ移動してください。上記の例では、`https://qltnci.deta.dev/docs` です。
-
-次のようなドキュメントが表示されます:
-
-
+
+```console
+$ pip install -r requirements.txt
+---> 100%
+Successfully installed fastapi pydantic uvicorn
+```
+
+
+
+/// info
+
+パッケージの依存関係を定義しインストールするためのフォーマットやツールは他にもあります。
+
+Poetryを使った例は、後述するセクションでご紹介します。👇
+
+///
-## **FastAPI** コードの作成
+### **FastAPI**コードを作成する
-* `app` ディレクトリを作成し、移動。
-* 以下の`main.py` ファイルを作成:
+* `app` ディレクトリを作成し、その中に入ります
+* 空のファイル `__init__.py` を作成します
+* `main.py` ファイルを作成します:
```Python
-from typing import Optional
+from typing import Union
from fastapi import FastAPI
@@ -78,23 +170,142 @@ def read_root():
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: Optional[str] = None):
+def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
-* ここでは、以下の様なディレクトリ構造になっているはずです:
+### Dockerfile
+
+同じプロジェクト・ディレクトリに`Dockerfile`というファイルを作成します:
+
+```{ .dockerfile .annotate }
+# (1)
+FROM python:3.9
+
+# (2)
+WORKDIR /code
+
+# (3)
+COPY ./requirements.txt /code/requirements.txt
+
+# (4)
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+
+# (5)
+COPY ./app /code/app
+
+# (6)
+CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
+```
+
+1. 公式のPythonベースイメージから始めます
+
+2. 現在の作業ディレクトリを `/code` に設定します
+
+ ここに `requirements.txt` ファイルと `app` ディレクトリを置きます。
+
+3. 要件が書かれたファイルを `/code` ディレクトリにコピーします
+
+ 残りのコードではなく、最初に必要なファイルだけをコピーしてください。
+
+ このファイルは**頻繁には変更されない**ので、Dockerはこのステップではそれを検知し**キャッシュ**を使用し、次のステップでもキャッシュを有効にします。
+
+4. 要件ファイルにあるパッケージの依存関係をインストールします
+ `--no-cache-dir` オプションはダウンロードしたパッケージをローカルに保存しないように `pip` に指示します。これは、同じパッケージをインストールするために `pip` を再度実行する場合にのみ有効ですが、コンテナで作業する場合はそうではないです。
+
+ /// note
+
+ `--no-cache-dir`は`pip`に関連しているだけで、Dockerやコンテナとは何の関係もないです。
+
+ ///
+
+ `--upgrade` オプションは、パッケージが既にインストールされている場合、`pip` にアップグレードするように指示します。
+
+ 何故ならファイルをコピーする前のステップは**Dockerキャッシュ**によって検出される可能性があるためであり、このステップも利用可能な場合は**Dockerキャッシュ**を使用します。
+
+ このステップでキャッシュを使用すると、開発中にイメージを何度もビルドする際に、**毎回**すべての依存関係を**ダウンロードしてインストールする**代わりに多くの**時間**を**節約**できます。
+
+5. ./app` ディレクトリを `/code` ディレクトリの中にコピーする。
+
+ これには**最も頻繁に変更される**すべてのコードが含まれているため、Dockerの**キャッシュ**は**これ以降のステップ**に簡単に使用されることはありません。
+
+ そのため、コンテナイメージのビルド時間を最適化するために、`Dockerfile`の **最後** にこれを置くことが重要です。
+
+6. `uvicorn`サーバーを実行するための**コマンド**を設定します
+
+ `CMD` は文字列のリストを取り、それぞれの文字列はスペースで区切られたコマンドラインに入力するものです。
+
+ このコマンドは **現在の作業ディレクトリ**から実行され、上記の `WORKDIR /code` にて設定した `/code` ディレクトリと同じです。
+
+ そのためプログラムは `/code` で開始しその中にあなたのコードがある `./app` ディレクトリがあるので、**Uvicorn** は `app.main` から `app` を参照し、**インポート** することができます。
+
+/// tip
+
+コード内の"+"の吹き出しをクリックして、各行が何をするのかをレビューしてください。👆
+
+///
+
+これで、次のようなディレクトリ構造になるはずです:
```
.
├── app
+│ ├── __init__.py
│ └── main.py
-└── Dockerfile
+├── Dockerfile
+└── requirements.txt
+```
+
+#### TLS Termination Proxyの裏側
+
+Nginx や Traefik のような TLS Termination Proxy (ロードバランサ) の後ろでコンテナを動かしている場合は、`--proxy-headers`オプションを追加します。
+
+このオプションは、Uvicornにプロキシ経由でHTTPSで動作しているアプリケーションに対して、送信されるヘッダを信頼するよう指示します。
+
+```Dockerfile
+CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
+```
+
+#### Dockerキャッシュ
+
+この`Dockerfile`には重要なトリックがあり、まず**依存関係だけのファイル**をコピーします。その理由を説明します。
+
+```Dockerfile
+COPY ./requirements.txt /code/requirements.txt
```
-## Dockerイメージをビルド
+Dockerや他のツールは、これらのコンテナイメージを**段階的に**ビルドし、**1つのレイヤーを他のレイヤーの上に**追加します。`Dockerfile`の先頭から開始し、`Dockerfile`の各命令によって作成されたファイルを追加していきます。
+
+Dockerや同様のツールは、イメージをビルドする際に**内部キャッシュ**も使用します。前回コンテナイメージを構築したときからファイルが変更されていない場合、ファイルを再度コピーしてゼロから新しいレイヤーを作成する代わりに、**前回作成した同じレイヤーを再利用**します。
-* プロジェクトディレクトリ (`app` ディレクトリを含んだ、`Dockerfile` のある場所) へ移動
-* FastAPIイメージのビルド:
+ただファイルのコピーを避けるだけではあまり改善されませんが、そのステップでキャッシュを利用したため、**次のステップ**でキャッシュを使うことができます。
+
+例えば、依存関係をインストールする命令のためにキャッシュを使うことができます:
+
+```Dockerfile
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+```
+
+パッケージ要件のファイルは**頻繁に変更されることはありません**。そのため、そのファイルだけをコピーすることで、Dockerはそのステップでは**キャッシュ**を使用することができます。
+
+そして、Dockerは**次のステップのためにキャッシュ**を使用し、それらの依存関係をダウンロードしてインストールすることができます。そして、ここで**多くの時間を節約**します。✨ ...そして退屈な待ち時間を避けることができます。😪😆
+
+パッケージの依存関係をダウンロードしてインストールするには**数分**かかりますが、**キャッシュ**を使えば**せいぜい数秒**です。
+
+加えて、開発中にコンテナ・イメージを何度もビルドして、コードの変更が機能しているかどうかをチェックすることになるため、多くの時間を節約することができます。
+
+そして`Dockerfile`の最終行の近くですべてのコードをコピーします。この理由は、**最も頻繁に**変更されるものなので、このステップの後にあるものはほとんどキャッシュを使用することができないのためです。
+
+```Dockerfile
+COPY ./app /code/app
+```
+
+### Dockerイメージをビルドする
+
+すべてのファイルが揃ったので、コンテナ・イメージをビルドしましょう。
+
+* プロジェクトディレクトリに移動します(`Dockerfile`がある場所で、`app`ディレクトリがあります)
+* FastAPI イメージをビルドします:
@@ -118,62 +337,412 @@ $ docker run -d --name mycontainer -p 80:80 myimage
-これで、Dockerコンテナ内に最適化されたFastAPIサーバが動作しています。使用しているサーバ (そしてCPUコア数) に沿った自動チューニングが行われています。
-
-## 確認
+## 確認する
-DockerコンテナのURLで確認できるはずです。例えば:
+これには、`asyncio` の高性能な完全互換品である `uvloop` が含まれ、並行処理のパフォーマンスが大幅に向上します。
- ```console
- $ pip install hypercorn
+///
- ---> 100%
- ```
+//// tab | Hypercorn
-
+*
+
+```console
+$ gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:80
+
+[19499] [INFO] Starting gunicorn 20.1.0
+[19499] [INFO] Listening at: http://0.0.0.0:80 (19499)
+[19499] [INFO] Using worker: uvicorn.workers.UvicornWorker
+[19511] [INFO] Booting worker with pid: 19511
+[19513] [INFO] Booting worker with pid: 19513
+[19514] [INFO] Booting worker with pid: 19514
+[19515] [INFO] Booting worker with pid: 19515
+[19511] [INFO] Started server process [19511]
+[19511] [INFO] Waiting for application startup.
+[19511] [INFO] Application startup complete.
+[19513] [INFO] Started server process [19513]
+[19513] [INFO] Waiting for application startup.
+[19513] [INFO] Application startup complete.
+[19514] [INFO] Started server process [19514]
+[19514] [INFO] Waiting for application startup.
+[19514] [INFO] Application startup complete.
+[19515] [INFO] Started server process [19515]
+[19515] [INFO] Waiting for application startup.
+[19515] [INFO] Application startup complete.
+```
+
+
+
+それぞれのオプションの意味を見てみましょう:
+
+* `main:app`: `main`は"`main`"という名前のPythonモジュール、つまりファイル`main.py`を意味します。そして `app` は **FastAPI** アプリケーションの変数名です。
+ * main:app`はPythonの`import`文と同じようなものだと想像できます:
+
+ ```Python
+ from main import app
+ ```
+
+ * つまり、`main:app`のコロンは、`from main import app`のPythonの`import`の部分と同じになります。
+
+* `--workers`: 使用するワーカー・プロセスの数で、それぞれがUvicornのワーカーを実行します。
+
+* `--worker-class`: ワーカー・プロセスで使用するGunicorn互換のワーカークラスです。
+ * ここではGunicornがインポートして使用できるクラスを渡します:
+
+ ```Python
+ import uvicorn.workers.UvicornWorker
+ ```
+
+* `--bind`: GunicornにリッスンするIPとポートを伝えます。コロン(`:`)でIPとポートを区切ります。
+ * Uvicornを直接実行している場合は、`--bind 0.0.0.0:80` (Gunicornのオプション)の代わりに、`--host 0.0.0.0`と `--port 80`を使います。
+
+出力では、各プロセスの**PID**(プロセスID)が表示されているのがわかります(単なる数字です)。
+
+以下の通りです:
+
+* Gunicornの**プロセス・マネージャー**はPID `19499`(あなたの場合は違う番号でしょう)で始まります。
+* 次に、`Listening at: http://0.0.0.0:80`を開始します。
+* それから `uvicorn.workers.UvicornWorker` でワーカークラスを使用することを検出します。
+* そして、**4つのワーカー**を起動します。それぞれのワーカーのPIDは、`19511`、`19513`、`19514`、`19515`です。
+
+Gunicornはまた、ワーカーの数を維持するために必要であれば、**ダウンしたプロセス**を管理し、**新しいプロセスを**再起動**させます。そのため、上記のリストにある**再起動**の概念に一部役立ちます。
+
+しかしながら、必要であればGunicornを**再起動**させ、**起動時に実行**させるなど、外部のコンポーネントを持たせることも必要かもしれません。
+
+## Uvicornとワーカー
+
+Uvicornには複数の**ワーカー・プロセス**を起動し実行するオプションもあります。
+
+とはいうものの、今のところUvicornのワーカー・プロセスを扱う機能はGunicornよりも制限されています。そのため、このレベル(Pythonレベル)でプロセスマネージャーを持ちたいのであれば、Gunicornをプロセスマネージャーとして使ってみた方が賢明かもしれないです。
+
+どんな場合であれ、以下のように実行します:
+
+
+
+```console
+// You could create an env var MY_NAME with
+$ export MY_NAME="Wade Wilson"
+
+// Then you could use it with other programs, like
+$ echo "Hello $MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+
+```console
+// Create an env var MY_NAME
+$ $Env:MY_NAME = "Wade Wilson"
+
+// Use it with other programs, like
+$ echo "Hello $Env:MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+## Pythonで環境変数を読み取る
+
+環境変数をPythonの**外側**、ターミナル(や他の方法)で作成し、**Python内で読み取る**こともできます。
+
+例えば、以下のような`main.py`ファイルを用意します:
+
+```Python hl_lines="3"
+import os
+
+name = os.getenv("MY_NAME", "World")
+print(f"Hello {name} from Python")
+```
+
+/// tip
+
+
+
+```console
+// Here we don't set the env var yet
+$ python main.py
+
+// As we didn't set the env var, we get the default value
+
+Hello World from Python
+
+// But if we create an environment variable first
+$ export MY_NAME="Wade Wilson"
+
+// And then call the program again
+$ python main.py
+
+// Now it can read the environment variable
+
+Hello Wade Wilson from Python
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+// Here we don't set the env var yet
+$ python main.py
+
+// As we didn't set the env var, we get the default value
+
+Hello World from Python
+
+// But if we create an environment variable first
+$ $Env:MY_NAME = "Wade Wilson"
+
+// And then call the program again
+$ python main.py
+
+// Now it can read the environment variable
+
+Hello Wade Wilson from Python
+```
+
+
+
+////
+
+環境変数はコードの外側で設定し、内側から読み取ることができるので、他のファイルと一緒に(`git`に)保存する必要がありません。そのため、環境変数をコンフィグレーションや**設定**に使用することが一般的です。
+
+また、**特定のプログラムの呼び出し**のための環境変数を、そのプログラムのみ、その実行中に限定して利用できるよう作成できます。
+
+そのためには、プログラム起動コマンドと同じコマンドライン上の、起動コマンド直前で環境変数を作成してください。
+
+
+
+```console
+// Create an env var MY_NAME in line for this program call
+$ MY_NAME="Wade Wilson" python main.py
+
+// Now it can read the environment variable
+
+Hello Wade Wilson from Python
+
+// The env var no longer exists afterwards
+$ python main.py
+
+Hello World from Python
+```
+
+
+
+/// tip
+
+詳しくは
+
+```console
+$ openssl rand -hex 32
+
+09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7
+```
+
+
+
+E copie a saída para a variável `SECRET_KEY` (não use a do exemplo).
+
+Crie uma variável `ALGORITHM` com o algoritmo usado para assinar o token JWT e defina como `"HS256"`.
+
+Crie uma variável para a expiração do token.
+
+Defina um modelo Pydantic que será usado no endpoint de token para a resposta.
+
+Crie uma função utilitária para gerar um novo token de acesso.
+
+{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *}
+
+## Atualize as dependências
+
+Atualize `get_current_user` para receber o mesmo token de antes, mas desta vez, usando tokens JWT.
+
+Decodifique o token recebido, verifique-o e retorne o usuário atual.
+
+Se o token for inválido, retorne um erro HTTP imediatamente.
+
+{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *}
+
+## Atualize a *operação de rota* `/token`
+
+Crie um `timedelta` com o tempo de expiração do token.
+
+Crie um token de acesso JWT real e o retorne.
+
+{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *}
+
+### Detalhes técnicos sobre o "sujeito" `sub` do JWT
+
+A especificação JWT diz que existe uma chave `sub`, com o sujeito do token.
+
+É opcional usá-la, mas é onde você colocaria a identificação do usuário, então nós estamos usando aqui.
+
+O JWT pode ser usado para outras coisas além de identificar um usuário e permitir que ele execute operações diretamente na sua API.
+
+Por exemplo, você poderia identificar um "carro" ou uma "postagem de blog".
+
+Depois, você poderia adicionar permissões sobre essa entidade, como "dirigir" (para o carro) ou "editar" (para o blog).
+
+E então, poderia dar esse token JWT para um usuário (ou bot), e ele poderia usá-lo para realizar essas ações (dirigir o carro ou editar o blog) sem sequer precisar ter uma conta, apenas com o token JWT que sua API gerou para isso.
+
+Usando essas ideias, o JWT pode ser usado para cenários muito mais sofisticados.
+
+Nesses casos, várias dessas entidades poderiam ter o mesmo ID, digamos `foo` (um usuário `foo`, um carro `foo` e uma postagem de blog `foo`).
+
+Então, para evitar colisões de ID, ao criar o token JWT para o usuário, você poderia prefixar o valor da chave `sub`, por exemplo, com `username:`. Assim, neste exemplo, o valor de `sub` poderia ser: `username:johndoe`.
+
+O importante a se lembrar é que a chave `sub` deve ter um identificador único em toda a aplicação e deve ser uma string.
+
+## Testando
+
+Execute o servidor e vá para a documentação:
+
+```console
+$ pytest
+
+================ test session starts ================
+platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
+rootdir: /home/user/code/superawesome-cli/app
+plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1
+collected 6 items
+
+---> 100%
+
+test_main.py ...... [100%]
+
+================= 1 passed in 0.03s =================
+```
+
+
diff --git a/docs/pt/docs/virtual-environments.md b/docs/pt/docs/virtual-environments.md
new file mode 100644
index 000000000..5fc1a8866
--- /dev/null
+++ b/docs/pt/docs/virtual-environments.md
@@ -0,0 +1,844 @@
+# Ambientes Virtuais
+
+Ao trabalhar em projetos Python, você provavelmente deve usar um **ambiente virtual** (ou um mecanismo similar) para isolar os pacotes que você instala para cada projeto.
+
+/// info | Informação
+
+Se você já sabe sobre ambientes virtuais, como criá-los e usá-los, talvez seja melhor pular esta seção. 🤓
+
+///
+
+/// tip | Dica
+
+Um **ambiente virtual** é diferente de uma **variável de ambiente**.
+
+Uma **variável de ambiente** é uma variável no sistema que pode ser usada por programas.
+
+Um **ambiente virtual** é um diretório com alguns arquivos.
+
+///
+
+/// info | Informação
+
+Esta página lhe ensinará como usar **ambientes virtuais** e como eles funcionam.
+
+Se você estiver pronto para adotar uma **ferramenta que gerencia tudo** para você (incluindo a instalação do Python), experimente
+
+```console
+// Vá para o diretório inicial
+$ cd
+// Crie um diretório para todos os seus projetos de código
+$ mkdir code
+// Entre nesse diretório de código
+$ cd code
+// Crie um diretório para este projeto
+$ mkdir awesome-project
+// Entre no diretório do projeto
+$ cd awesome-project
+```
+
+
+
+## Crie um ambiente virtual
+
+Ao começar a trabalhar em um projeto Python **pela primeira vez**, crie um ambiente virtual **
+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+
+
+Se ele mostrar o binário `python` em `.venv/bin/python`, dentro do seu projeto (neste caso `awesome-project`), então funcionou. 🎉
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ Get-Command python
+
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+
+
+Se ele mostrar o binário `python` em `.venv\Scripts\python`, dentro do seu projeto (neste caso `awesome-project`), então funcionou. 🎉
+
+////
+
+## Atualizar `pip`
+
+/// tip | Dica
+
+Se você usar
+
+```console
+// Não execute isso agora, é apenas um exemplo 🤓
+$ pip install "fastapi[standard]"
+---> 100%
+```
+
+
+
+Isso fará o download de um arquivo compactado com o código FastAPI, normalmente do
+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ Get-Command python
+
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+
+
+////
+
+Isso significa que o programa `python` que será usado é aquele **no ambiente virtual**.
+
+você usa `which` no Linux e macOS e `Get-Command` no Windows PowerShell.
+
+A maneira como esse comando funciona é que ele vai e verifica na variável de ambiente `PATH`, passando por **cada caminho em ordem**, procurando pelo programa chamado `python`. Uma vez que ele o encontre, ele **mostrará o caminho** para esse programa.
+
+A parte mais importante é que quando você chama ``python`, esse é exatamente o "`python`" que será executado.
+
+Assim, você pode confirmar se está no ambiente virtual correto.
+
+/// tip | Dica
+
+É fácil ativar um ambiente virtual, obter um Python e então **ir para outro projeto**.
+
+E o segundo projeto **não funcionaria** porque você está usando o **Python incorreto**, de um ambiente virtual para outro projeto.
+
+É útil poder verificar qual `python` está sendo usado. 🤓
+
+///
+
+## Por que desativar um ambiente virtual
+
+Por exemplo, você pode estar trabalhando em um projeto `philosophers-stone`, **ativar esse ambiente virtual**, instalar pacotes e trabalhar com esse ambiente.
+
+E então você quer trabalhar em **outro projeto** `prisoner-of-azkaban`.
+
+Você vai para aquele projeto:
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+
+$ python main.py
+
+// Erro ao importar o Sirius, ele não está instalado 😱
+Traceback (most recent call last):
+ File "main.py", line 1, in
+ import sirius
+```
+
+
+
+Mas se você desativar o ambiente virtual e ativar o novo para `prisoner-of-askaban`, quando você executar `python`, ele usará o Python do ambiente virtual em `prisoner-of-azkaban`.
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+
+// Você não precisa estar no diretório antigo para desativar, você pode fazer isso de onde estiver, mesmo depois de ir para o outro projeto 😎
+$ deactivate
+
+// Ative o ambiente virtual em prisoner-of-azkaban/.venv 🚀
+$ source .venv/bin/activate
+
+// Agora, quando você executar o python, ele encontrará o pacote sirius instalado neste ambiente virtual ✨
+$ python main.py
+
+Eu juro solenemente 🐺
+```
+
+
+
+## Alternativas
+
+Este é um guia simples para você começar e lhe ensinar como tudo funciona **por baixo**.
+
+Existem muitas **alternativas** para gerenciar ambientes virtuais, dependências de pacotes (requisitos) e projetos.
+
+Quando estiver pronto e quiser usar uma ferramenta para **gerenciar todo o projeto**, dependências de pacotes, ambientes virtuais, etc., sugiro que você experimente o
+
+```console
+$ pip install -r requirements.txt
+---> 100%
+Successfully installed fastapi pydantic uvicorn
+```
+
+
+
+/// info | Информация
+
+Существуют и другие инструменты управления зависимостями.
+
+В этом же разделе, но позже, я покажу вам пример использования Poetry. 👇
+
+///
+
+### Создать приложение **FastAPI**
+
+* Создайте директорию `app` и перейдите в неё.
+* Создайте пустой файл `__init__.py`.
+* Создайте файл `main.py` и заполните его:
+
+```Python
+from typing import Union
+
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+def read_root():
+ return {"Hello": "World"}
+
+
+@app.get("/items/{item_id}")
+def read_item(item_id: int, q: Union[str, None] = None):
+ return {"item_id": item_id, "q": q}
+```
+
+### Dockerfile
+
+В этой же директории создайте файл `Dockerfile` и заполните его:
+
+```{ .dockerfile .annotate }
+# (1)
+FROM python:3.9
+
+# (2)
+WORKDIR /code
+
+# (3)
+COPY ./requirements.txt /code/requirements.txt
+
+# (4)
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+
+# (5)
+COPY ./app /code/app
+
+# (6)
+CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
+```
+
+1. Начните с официального образа Python, который будет основой для образа приложения.
+
+2. Укажите, что в дальнейшем команды запускаемые в контейнере, будут выполняться в директории `/code`.
+
+ Инструкция создаст эту директорию внутри контейнера и мы поместим в неё файл `requirements.txt` и директорию `app`.
+
+3. Скопируете файл с зависимостями из текущей директории в `/code`.
+
+ Сначала копируйте **только** файл с зависимостями.
+
+ Этот файл **изменяется довольно редко**, Docker ищет изменения при постройке образа и если не находит, то использует **кэш**, в котором хранятся предыдущие версии сборки образа.
+
+4. Установите библиотеки перечисленные в файле с зависимостями.
+
+ Опция `--no-cache-dir` указывает `pip` не сохранять загружаемые библиотеки на локальной машине для использования их в случае повторной загрузки. В контейнере, в случае пересборки этого шага, они всё равно будут удалены.
+
+ /// note | Заметка
+
+ Опция `--no-cache-dir` нужна только для `pip`, она никак не влияет на Docker или контейнеры.
+
+ ///
+
+ Опция `--upgrade` указывает `pip` обновить библиотеки, емли они уже установлены.
+
+ Как и в предыдущем шаге с копированием файла, этот шаг также будет использовать **кэш Docker** в случае отсутствия изменений.
+
+ Использование кэша, особенно на этом шаге, позволит вам **сэкономить** кучу времени при повторной сборке образа, так как зависимости будут сохранены в кеше, а не **загружаться и устанавливаться каждый раз**.
+
+5. Скопируйте директорию `./app` внутрь директории `/code` (в контейнере).
+
+ Так как в этой директории расположен код, который **часто изменяется**, то использование **кэша** на этом шаге будет наименее эффективно, а значит лучше поместить этот шаг **ближе к концу** `Dockerfile`, дабы не терять выгоду от оптимизации предыдущих шагов.
+
+6. Укажите **команду**, запускающую сервер `uvicorn`.
+
+ `CMD` принимает список строк, разделённых запятыми, но при выполнении объединит их через пробел, собрав из них одну команду, которую вы могли бы написать в терминале.
+
+ Эта команда будет выполнена в **текущей рабочей директории**, а именно в директории `/code`, которая указана в команде `WORKDIR /code`.
+
+ Так как команда выполняется внутри директории `/code`, в которую мы поместили папку `./app` с приложением, то **Uvicorn** сможет найти и **импортировать** объект `app` из файла `app.main`.
+
+/// tip | Подсказка
+
+Если ткнёте на кружок с плюсом, то увидите пояснения. 👆
+
+///
+
+На данном этапе структура проекта должны выглядеть так:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ └── main.py
+├── Dockerfile
+└── requirements.txt
+```
+
+#### Использование прокси-сервера
+
+Если вы запускаете контейнер за прокси-сервером завершения TLS (балансирующего нагрузку), таким как Nginx или Traefik, добавьте опцию `--proxy-headers`, которая укажет Uvicorn, что он работает позади прокси-сервера и может доверять заголовкам отправляемым им.
+
+```Dockerfile
+CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
+```
+
+#### Кэш Docker'а
+
+В нашем `Dockerfile` использована полезная хитрость, когда сначала копируется **только файл с зависимостями**, а не вся папка с кодом приложения.
+
+```Dockerfile
+COPY ./requirements.txt /code/requirements.txt
+```
+
+Docker и подобные ему инструменты **создают** образы контейнеров **пошагово**, добавляя **один слой над другим**, начиная с первой строки `Dockerfile` и добавляя файлы, создаваемые при выполнении каждой инструкции из `Dockerfile`.
+
+При создании образа используется **внутренний кэш** и если в файлах нет изменений с момента последней сборки образа, то будет **переиспользован** ранее созданный слой образа, а не повторное копирование файлов и создание слоя с нуля.
+Заметьте, что так как слой следующего шага зависит от слоя предыдущего, то изменения внесённые в промежуточный слой, также повлияют на последующие.
+
+Избегание копирования файлов не обязательно улучшит ситуацию, но использование кэша на одном шаге, позволит **использовать кэш и на следующих шагах**. Например, можно использовать кэш при установке зависимостей:
+
+```Dockerfile
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+```
+
+Файл со списком зависимостей **изменяется довольно редко**. Так что выполнив команду копирования только этого файла, Docker сможет **использовать кэш** на этом шаге.
+
+А затем **использовать кэш и на следующем шаге**, загружающем и устанавливающем зависимости. И вот тут-то мы и **сэкономим много времени**. ✨ ...а не будем томиться в тягостном ожидании. 😪😆
+
+Для загрузки и установки необходимых библиотек **может понадобиться несколько минут**, но использование **кэша** занимает несколько **секунд** максимум.
+
+И так как во время разработки вы будете часто пересобирать контейнер для проверки работоспособности внесённых изменений, то сэкономленные минуты сложатся в часы, а то и дни.
+
+Так как папка с кодом приложения **изменяется чаще всего**, то мы расположили её в конце `Dockerfile`, ведь после внесённых в код изменений кэш не будет использован на этом и следующих шагах.
+
+```Dockerfile
+COPY ./app /code/app
+```
+
+### Создать Docker-образ
+
+Теперь, когда все файлы на своих местах, давайте создадим образ контейнера.
+
+* Перейдите в директорию проекта (в ту, где расположены `Dockerfile` и папка `app` с приложением).
+* Создай образ приложения FastAPI:
+
+
+
+```console
+$ hypercorn main:app --bind 0.0.0.0:80
+
+Running on 0.0.0.0:8080 over http (CTRL + C to quit)
+```
+
+
+
+////
+
+/// warning | Предупреждение
+
+Не забудьте удалить опцию `--reload`, если ранее пользовались ею.
+
+Включение опции `--reload` требует дополнительных ресурсов, влияет на стабильность работы приложения и может повлечь прочие неприятности.
+
+Она сильно помогает во время **разработки**, но **не следует** использовать её при **реальной работе** приложения.
+
+///
+
+## Hypercorn с Trio
+
+Starlette и **FastAPI** основаны на
+
+```console
+// Вы можете создать переменную окружения MY_NAME с помощью
+$ export MY_NAME="Wade Wilson"
+
+// Затем её можно использовать в других программах, например
+$ echo "Hello $MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+// Создайте переменную окружения MY_NAME
+$ $Env:MY_NAME = "Wade Wilson"
+
+// Используйте её с другими программами, например
+$ echo "Hello $Env:MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+## Чтение переменных окружения в python
+
+Так же существует возможность создания переменных окружения **вне** Python, в терминале (или любым другим способом), а затем **чтения их в Python**.
+
+Например, у вас есть файл `main.py`:
+
+```Python hl_lines="3"
+import os
+
+name = os.getenv("MY_NAME", "World")
+print(f"Hello {name} from Python")
+```
+
+/// tip
+
+Второй аргумент
+
+```console
+// Здесь мы еще не устанавливаем переменную окружения
+$ python main.py
+
+// Поскольку мы не задали переменную окружения, мы получим значение по умолчанию
+
+Hello World from Python
+
+// Но если мы сначала создадим переменную окружения
+$ export MY_NAME="Wade Wilson"
+
+// А затем снова запустим программу
+$ python main.py
+
+// Теперь она прочитает переменную окружения
+
+Hello Wade Wilson from Python
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+// Здесь мы еще не устанавливаем переменную окружения
+$ python main.py
+
+// Поскольку мы не задали переменную окружения, мы получим значение по умолчанию
+
+Hello World from Python
+
+// Но если мы сначала создадим переменную окружения
+$ $Env:MY_NAME = "Wade Wilson"
+
+// А затем снова запустим программу
+$ python main.py
+
+// Теперь она может прочитать переменную окружения
+
+Hello Wade Wilson from Python
+```
+
+
+
+////
+
+Поскольку переменные окружения могут быть установлены вне кода, но могут быть прочитаны кодом, и их не нужно хранить (фиксировать в `git`) вместе с остальными файлами, их принято использовать для конфигураций или **настроек**.
+
+Вы также можете создать переменную окружения только для **конкретного вызова программы**, которая будет доступна только для этой программы и только на время ее выполнения.
+
+Для этого создайте её непосредственно перед самой программой, в той же строке:
+
+
+
+```console
+// Создайте переменную окружения MY_NAME в строке для этого вызова программы
+$ MY_NAME="Wade Wilson" python main.py
+
+// Теперь она может прочитать переменную окружения
+
+Hello Wade Wilson from Python
+
+// После этого переменная окружения больше не существует
+$ python main.py
+
+Hello World from Python
+```
+
+
+
+/// tip
+
+Подробнее об этом можно прочитать на сайте
```console
-$ pip install uvicorn[standard]
+$ pip install "uvicorn[standard]"
---> 100%
```
-## Example
+## Пример
-### Create it
+### Создание
-* Create a file `main.py` with:
+* Создайте файл `main.py` со следующим содержимым:
```Python
-from typing import Optional
+from typing import Union
from fastapi import FastAPI
@@ -162,17 +164,17 @@ def read_root():
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: Optional[str] = None):
+def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
+
+```console
+$ openssl rand -hex 32
+
+09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7
+```
+
+
+
+И скопируйте полученный результат в переменную `SECRET_KEY` (не используйте тот, что в примере).
+
+Создайте переменную `ALGORITHM` с алгоритмом, используемым для подписи JWT-токена, и установите для нее значение `"HS256"`.
+
+Создайте переменную для срока действия токена.
+
+Определите Pydantic Model, которая будет использоваться для формирования ответа на запрос на получение токена.
+
+Создайте служебную функцию для генерации нового токена доступа.
+
+{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *}
+
+## Обновление зависимостей
+
+Обновите `get_current_user` для получения того же токена, что и раньше, но на этот раз с использованием JWT-токенов.
+
+Декодируйте полученный токен, проверьте его и верните текущего пользователя.
+
+Если токен недействителен, то сразу же верните HTTP-ошибку.
+
+{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *}
+
+## Обновление *операции пути* `/token`
+
+Создайте `timedelta` со временем истечения срока действия токена.
+
+Создайте реальный токен доступа JWT и верните его
+
+{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *}
+
+### Технические подробности о JWT ключе `sub`
+
+В спецификации JWT говорится, что существует ключ `sub`, содержащий субъект токена.
+
+Его использование необязательно, но это именно то место, куда вы должны поместить идентификатор пользователя, и поэтому мы здесь его и используем.
+
+JWT может использоваться и для других целей, помимо идентификации пользователя и предоставления ему возможности выполнять операции непосредственно в вашем API.
+
+Например, вы могли бы определить "автомобиль" или "запись в блоге".
+
+Затем вы могли бы добавить права доступа к этой сущности, например "управлять" (для автомобиля) или "редактировать" (для блога).
+
+Затем вы могли бы передать этот JWT-токен пользователю (или боту), и они использовали бы его для выполнения определенных действий (управление автомобилем или редактирование запись в блоге), даже не имея учетной записи, просто используя JWT-токен, сгенерированный вашим API.
+
+Используя эти идеи, JWT можно применять для гораздо более сложных сценариев.
+
+В отдельных случаях несколько сущностей могут иметь один и тот же идентификатор, скажем, `foo` (пользователь `foo`, автомобиль `foo` и запись в блоге `foo`).
+
+Поэтому, чтобы избежать коллизий идентификаторов, при создании JWT-токена для пользователя можно добавить префикс `username` к значению ключа `sub`. Таким образом, в данном примере значение `sub` было бы `username:johndoe`.
+
+Важно помнить, что ключ `sub` должен иметь уникальный идентификатор для всего приложения и представлять собой строку.
+
+## Проверка в действии
+
+Запустите сервер и перейдите к документации:
+
+```console
+$ pytest
+
+================ test session starts ================
+platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
+rootdir: /home/user/code/superawesome-cli/app
+plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1
+collected 6 items
+
+---> 100%
+
+test_main.py ...... [100%]
+
+================= 1 passed in 0.03s =================
+```
+
+
diff --git a/docs/ru/docs/virtual-environments.md b/docs/ru/docs/virtual-environments.md
new file mode 100644
index 000000000..777adaf22
--- /dev/null
+++ b/docs/ru/docs/virtual-environments.md
@@ -0,0 +1,839 @@
+# Виртуальная среда
+
+При работе с проектами в Python рекомендуется использовать **виртуальную среду разработки** (или какой-нибудь другой подобный механизм). Это нужно для того, чтобы изолировать устанавливаемые пакеты для каждого отдельного проекта.
+
+/// info | Дополнительная информация
+
+Если вы уже знакомы с виртуальными средами разработки, знаете как их создавать и использовать, то вы можете свободно пропустить данный раздел. 🤓
+
+///
+
+/// tip | Подсказка
+
+**Виртуальная среда** и **переменная окружения** это две разные вещи.
+
+**Переменная окружения** это системная переменная, которую могут использовать программы.
+
+**Виртуальная среда** это папка, содержащая файлы.
+
+///
+
+/// info | Дополнительная информация
+
+В этом разделе мы научим вас пользоваться виртуальными средами разработки и расскажем, как они работают.
+
+Если же вы готовы воспользоваться инструментом, **который умеет управлять всем, что касается Python-проектов**,
+(включая установку Python), то попробуйте
+
+```console
+// Перейдите в домашний каталог
+$ cd
+// Создайте отдельную папку под все будущие программные проекты (code)
+$ mkdir code
+// Войдите в директорию code
+$ cd code
+// Создайте директрорию под данный проект (awesome-project)
+$ mkdir awesome-project
+// Перейдите в созданную директорию проекта
+$ cd awesome-project
+```
+
+
+
+## Создание виртуальной среды разработки
+
+Начиная работу с Python-проектом, сразу же создавайте виртуальную среду разработки
+**
+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+
+
+Если данная команда показывает, что исполняемый файл `python` (`.venv\bin\python`), находится внутри виртуальной среды вашего проекта (у нас это `awesome-project`), значит все отработало как нужно. 🎉
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ Get-Command python
+
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+
+
+Если данная команда показывает, что исполняемый файл `python` (`.venv\Scripts\python`), находится внутри виртуальной среды вашего проекта (у нас это `awesome-project`), значит все отработало как нужно. 🎉
+
+////
+
+## Обновление `pip`
+
+/// tip | Подсказка
+
+Если вы используете
+
+```console
+// Не запускайте эту команду, это просто пример 🤓
+$ pip install "fastapi[standard]"
+---> 100%
+```
+
+
+
+То будет скачан сжатый файл, содержащий код FastAPI, обычно скачивание происходит с
+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ Get-Command python
+
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+
+
+////
+
+Это означает, что будет использоваться `python` **из виртуальной среды разработки**.
+
+Вы используете `which` для Linux и macOS и `Get-Command` для Windows PowerShell.
+
+Эта команда работает следующим образом: она проверяет переменную окружения `PATH`, проходя по очереди каждый указанный путь в поисках программы под названием `python`. И когда она её находит, то возвращает путь к данной программе.
+
+Основной момент при вызове команды `python` состоит в том, какой именно "`python`" будет запущен.
+
+Таким образом, вы можете убедиться, что используете правильную виртуальную среду разработки.
+
+/// tip | Подсказка
+
+Легко активировать одну виртуальную среду, вызвать один Python и **перейти к следующему проекту**.
+
+И следующий проект не будет работать потому, что вы используете **неправильный Python** из виртуальной среды другого проекта.
+
+Так что, будет нелишним проверить, какой `python` вы используете. 🤓
+
+///
+
+## Зачем деактивируют виртуальную среду?
+
+Предположим, что вы работаете над проектом `philosophers-stone`, **активируете виртуальную среду разработки**, устанавливаете пакеты и работаете с данной средой.
+
+И позже вам понадобилось поработать с **другим проектом** `prisoner-of-azkaban`.
+
+Вы переходите к этому проекту:
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+
+$ python main.py
+
+// Error importing sirius, it's not installed 😱
+Traceback (most recent call last):
+ File "main.py", line 1, in
+ import sirius
+```
+
+
+
+Но если вы деактивируете виртуальную среду разработки и активируете новую среду для `prisoner-of-askaban`, то вы тогда запустите Python из виртуального окружения `prisoner-of-azkaban`.
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+
+// Вам не требуется находится в старой директории для деактивации среды разработки, вы можете это сделать откуда угодно, даже из каталога другого проекта, в который вы перешли. 😎
+$ deactivate
+
+// Активируйте виртуальную среду разработки в prisoner-of-azkaban/.venv 🚀
+$ source .venv/bin/activate
+
+// Тепреь, когда вы запустите python, он найдет пакет sirius, установленный в виртуальной среде ✨
+$ python main.py
+
+Я торжественно клянусь в этом! 🐺
+```
+
+
+
+## Альтернативы
+
+Это простое руководство поможет вам начать работу и научит тому, как всё работает **изнутри**.
+
+Существует много альтернативных решений для работы с виртуальными средами разработки, с программными зависимостями, а также с проектами.
+
+Когда вы будете готовы использовать единый инструмент для управления проектом, программными зависимостями, виртуальными средами разработки и т.д., то я рекомендую вам попробовать
-
-```console
-$ uvicorn main:app --reload
-
-INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
-INFO: Started reloader process [28720]
-INFO: Started server process [28722]
-INFO: Waiting for application startup.
-INFO: Application startup complete.
-```
-
-
-
-
```console
-$ pip install uvicorn[standard]
+$ pip install "uvicorn[standard]"
---> 100%
```
@@ -152,12 +152,12 @@ $ pip install uvicorn[standard]
## Örnek
-### Şimdi dene
+### Kodu Oluşturalım
-* `main.py` adında bir dosya oluştur :
+* `main.py` adında bir dosya oluşturup içine şu kodu yapıştıralım:
```Python
-from typing import Optional
+from typing import Union
from fastapi import FastAPI
@@ -170,17 +170,17 @@ def read_root():
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: Optional[str] = None):
+def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
Ya da async def
...
-Eğer kodunda `async` / `await` var ise, `async def` kullan:
+Eğer kodunuzda `async` / `await` varsa, `async def` kullanalım:
-```Python hl_lines="9 14"
-from typing import Optional
+```Python hl_lines="9 14"
+from typing import Union
from fastapi import FastAPI
@@ -193,19 +193,19 @@ async def read_root():
@app.get("/items/{item_id}")
-async def read_item(item_id: int, q: Optional[str] = None):
+async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
**Not**:
-Eğer ne olduğunu bilmiyor isen _"Acelen mi var?"_ kısmını oku `async` ve `await`.
+Eğer bu konu hakkında bilginiz yoksa `async` ve `await` dokümantasyonundaki _"Aceleniz mi var?"_ kısmını kontrol edebilirsiniz.
-### Çalıştır
+### Kodu Çalıştıralım
-Serverı aşağıdaki komut ile çalıştır:
+Sunucuyu aşağıdaki komutla çalıştıralım:
@@ -222,57 +222,57 @@ INFO: Application startup complete.
-Çalıştırdığımız uvicorn main:app --reload
hakkında...
+uvicorn main:app --reload
komutuyla ilgili...
-`uvicorn main:app` şunları ifade ediyor:
+`uvicorn main:app` komutunu şu şekilde açıklayabiliriz:
* `main`: dosya olan `main.py` (yani Python "modülü").
-* `app`: ise `main.py` dosyasının içerisinde oluşturduğumuz `app = FastAPI()` 'a denk geliyor.
-* `--reload`: ise kodda herhangi bir değişiklik yaptığımızda serverın yapılan değişiklerileri algılayıp, değişiklikleri siz herhangi bir şey yapmadan uygulamasını sağlıyor.
+* `app`: ise `main.py` dosyasının içerisinde `app = FastAPI()` satırında oluşturduğumuz `FastAPI` nesnesi.
+* `--reload`: kod değişikliklerinin ardından sunucuyu otomatik olarak yeniden başlatır. Bu parameteyi sadece geliştirme aşamasında kullanmalıyız.
-### Dokümantasyonu kontrol et
+### Şimdi de Kontrol Edelim
-Browserını aç ve şu linke git
http://127.0.0.1:8000/items/5?q=somequery.
+Tarayıcımızda şu bağlantıyı açalım
http://127.0.0.1:8000/items/5?q=somequery.
-Bir JSON yanıtı göreceksin:
+Aşağıdaki gibi bir JSON yanıtıyla karşılaşacağız:
```JSON
{"item_id": 5, "q": "somequery"}
```
-Az önce oluşturduğun API:
+Az önce oluşturduğumuz API:
-* `/` ve `/items/{item_id}` adreslerine HTTP talebi alabilir hale geldi.
-* İki _adresde_ `GET`
operasyonlarını (HTTP _metodları_ olarakta bilinen) yapabilir hale geldi.
-* `/items/{item_id}` _adresi_ ayrıca bir `item_id` _adres parametresine_ sahip ve bu bir `int` olmak zorunda.
-* `/items/{item_id}` _adresi_ opsiyonel bir `str` _sorgu paramtersine_ sahip bu da `q`.
+* `/` ve `/items/{item_id}`
_yollarına_ HTTP isteği alabilir.
+* İki _yolda_ `GET`
operasyonlarını (HTTP _metodları_ olarak da bilinen) kabul ediyor.
+* `/items/{item_id}` _yolu_ `item_id` adında bir _yol parametresine_ sahip ve bu parametre `int` değer almak zorundadır.
+* `/items/{item_id}` _yolu_ `q` adında bir _yol parametresine_ sahip ve bu parametre opsiyonel olmakla birlikte, `str` değer almak zorundadır.
-### İnteraktif API dokümantasyonu
+### Etkileşimli API Dokümantasyonu
-Şimdi
http://127.0.0.1:8000/docs adresine git.
+Şimdi
http://127.0.0.1:8000/docs bağlantısını açalım.
-Senin için otomatik oluşturulmuş(
Swagger UI tarafından sağlanan) interaktif bir API dokümanı göreceksin:
+
Swagger UI tarafından sağlanan otomatik etkileşimli bir API dokümantasyonu göreceğiz:

-### Alternatif API dokümantasyonu
+### Alternatif API Dokümantasyonu
-Şimdi
http://127.0.0.1:8000/redoc adresine git.
+Şimdi
http://127.0.0.1:8000/redoc bağlantısını açalım.
-Senin için alternatif olarak (
ReDoc tarafından sağlanan) bir API dokümantasyonu daha göreceksin:
+
ReDoc tarafından sağlanan otomatik dokümantasyonu göreceğiz:

-## Örnek bir değişiklik
+## Örneği Güncelleyelim
-Şimdi `main.py` dosyasını değiştirelim ve body ile `PUT` talebi alabilir hale getirelim.
+Şimdi `main.py` dosyasını, `PUT` isteğiyle birlikte bir gövde alacak şekilde değiştirelim.
-Şimdi Pydantic sayesinde, Python'un standart tiplerini kullanarak bir body tanımlayacağız.
+
Gövdeyi Pydantic sayesinde standart python tiplerini kullanarak tanımlayalım.
-```Python hl_lines="4 9 10 11 12 25 26 27"
-from typing import Optional
+```Python hl_lines="4 9-12 25-27"
+from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
@@ -283,7 +283,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
- is_offer: Optional[bool] = None
+ is_offer: Union[bool, None] = None
@app.get("/")
@@ -292,7 +292,7 @@ def read_root():
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: Optional[str] = None):
+def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
@@ -301,41 +301,41 @@ def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
-Server otomatik olarak yeniden başlamalı (çünkü yukarıda `uvicorn`'u çalıştırırken `--reload` parametresini kullandık.).
+Sunucu otomatik olarak yeniden başlamış olmalı (çünkü yukarıda `uvicorn` komutuyla birlikte `--reload` parametresini kullandık).
-### İnteraktif API dokümantasyonu'nda değiştirme yapmak
+### Etkileşimli API Dokümantasyonundaki Değişimi Görelim
-Şimdi
http://127.0.0.1:8000/docs bağlantısına tekrar git.
+Şimdi
http://127.0.0.1:8000/docs bağlantısına tekrar gidelim.
-* İnteraktif API dokümantasyonu, yeni body ile beraber çoktan yenilenmiş olması lazım:
+* Etkileşimli API dokümantasyonu, yeni gövdede dahil olmak üzere otomatik olarak güncellenmiş olacak:

-* "Try it out"a tıkla, bu senin API parametleri üzerinde deneme yapabilmene izin veriyor:
+* "Try it out" butonuna tıklayalım, bu işlem API parametleri üzerinde değişiklik yapmamıza ve doğrudan API ile etkileşime geçmemize imkan sağlayacak:

-* Şimdi "Execute" butonuna tıkla, kullanıcı arayüzü otomatik olarak API'ın ile bağlantı kurarak ona bu parametreleri gönderecek ve sonucu karşına getirecek.
+* Şimdi "Execute" butonuna tıklayalım, kullanıcı arayüzü API'ımız ile bağlantı kurup parametreleri gönderecek ve sonucu ekranımıza getirecek:

-### Alternatif API dokümantasyonunda değiştirmek
+### Alternatif API Dokümantasyonundaki Değişimi Görelim
-Şimdi ise
http://127.0.0.1:8000/redoc adresine git.
+Şimdi ise
http://127.0.0.1:8000/redoc bağlantısına tekrar gidelim.
-* Alternatif dokümantasyonda koddaki değişimler ile beraber kendini yeni query ve body ile güncelledi.
+* Alternatif dokümantasyonda yaptığımız değişiklikler ile birlikte yeni sorgu parametresi ve gövde bilgisi ile güncelemiş olacak:

### Özet
-Özetleyecek olursak, URL, sorgu veya request body'deki parametrelerini fonksiyon parametresi olarak kullanıyorsun. Bu parametrelerin veri tiplerini bir kere belirtmen yeterli.
+Özetlemek gerekirse, parametrelerin, gövdenin, vb. veri tiplerini fonksiyon parametreleri olarak **bir kere** tanımlıyoruz.
-Type-hinting işlemini Python dilindeki standart veri tipleri ile yapabilirsin
+Bu işlemi standart modern Python tipleriyle yapıyoruz.
-Yeni bir syntax'e alışmana gerek yok, metodlar ve classlar zaten spesifik kütüphanelere ait.
+Yeni bir sözdizimi yapısını, bir kütüphane özel metod veya sınıfları öğrenmeye gerek yoktur.
-Sadece standart **Python 3.6+**.
+Hepsi sadece **Python** standartlarına dayalıdır.
Örnek olarak, `int` tanımlamak için:
@@ -343,64 +343,64 @@ Sadece standart **Python 3.6+**.
item_id: int
```
-ya da daha kompleks `Item` tipi:
+ya da daha kompleks herhangi bir python modelini tanımlayabiliriz, örneğin `Item` modeli için:
```Python
item: Item
```
-...sadece kısa bir parametre tipi belirtmekle beraber, sahip olacakların:
+...ve sadece kısa bir parametre tipi belirterek elde ettiklerimiz:
-* Editör desteği dahil olmak üzere:
+* Editör desteğiyle birlikte:
* Otomatik tamamlama.
- * Tip sorguları.
-* Datanın tipe uyumunun sorgulanması:
- * Eğer data geçersiz ise, otomatik olarak hataları ayıklar.
- * Çok derin JSON objelerinde bile veri tipi sorgusu yapar.
-* Gelen verinin
dönüşümünü aşağıdaki veri tiplerini kullanarak gerçekleştirebiliyor.
+ * Tip kontrolü.
+* Veri Doğrulama:
+ * Veri geçerli değilse, otomatik olarak açıklayıcı hatalar gösterir.
+ * Çok
derin JSON nesnelerinde bile doğrulama yapar.
+* Gelen verinin
dönüşümünü aşağıdaki veri tiplerini kullanarak gerçekleştirir:
* JSON.
- * Path parametreleri.
- * Query parametreleri.
- * Cookies.
+ * Yol parametreleri.
+ * Sorgu parametreleri.
+ * Çerezler.
* Headers.
- * Forms.
- * Files.
-* Giden verinin
dönüşümünü aşağıdaki veri tiplerini kullanarak gerçekleştirebiliyor (JSON olarak):
- * Python tiplerinin (`str`, `int`, `float`, `bool`, `list`, vs) çevirisi.
- * `datetime` objesi.
- * `UUID` objesi.
+ * Formlar.
+ * Dosyalar.
+* Giden verinin
dönüşümünü aşağıdaki veri tiplerini kullanarak gerçekleştirir (JSON olarak):
+ * Python tiplerinin (`str`, `int`, `float`, `bool`, `list`, vb) dönüşümü.
+ * `datetime` nesnesi.
+ * `UUID` nesnesi.
* Veritabanı modelleri.
- * ve daha fazlası...
-* 2 alternatif kullanıcı arayüzü dahil olmak üzere, otomatik interaktif API dokümanu:
+ * ve çok daha fazlası...
+* 2 alternatif kullanıcı arayüzü dahil olmak üzere, otomatik etkileşimli API dokümantasyonu sağlar:
* Swagger UI.
* ReDoc.
---
-Az önceki kod örneğine geri dönelim, **FastAPI**'ın yapacaklarına bir bakış atalım:
+Az önceki örneğe geri dönelim, **FastAPI**'ın yapacaklarına bir bakış atalım:
-* `item_id`'nin `GET` ve `PUT` talepleri içinde olup olmadığının doğruluğunu kontol edecek.
-* `item_id`'nin tipinin `int` olduğunu `GET` ve `PUT` talepleri içinde olup olmadığının doğruluğunu kontol edecek.
- * Eğer `GET` ve `PUT` içinde yok ise ve `int` değil ise, sebebini belirten bir hata mesajı gösterecek
-* Opsiyonel bir `q` parametresinin `GET` talebi için (`http://127.0.0.1:8000/items/foo?q=somequery` içinde) olup olmadığını kontrol edecek
+* `item_id`'nin `GET` ve `PUT` istekleri için, yolda olup olmadığının kontol edecek.
+* `item_id`'nin `GET` ve `PUT` istekleri için, tipinin `int` olduğunu doğrulayacak.
+ * Eğer değilse, sebebini belirten bir hata mesajı gösterecek.
+* Opsiyonel bir `q` parametresinin `GET` isteği içinde (`http://127.0.0.1:8000/items/foo?q=somequery` gibi) olup olmadığını kontrol edecek
* `q` parametresini `= None` ile oluşturduğumuz için, opsiyonel bir parametre olacak.
- * Eğer `None` olmasa zorunlu bir parametre olacak idi (bu yüzden body'de `PUT` parametresi var).
-* `PUT` talebi için `/items/{item_id}`'nin body'sini, JSON olarak okuyor:
- * `name` adında bir parametetre olup olmadığını ve var ise onun `str` olup olmadığını kontol ediyor.
- * `price` adında bir parametetre olup olmadığını ve var ise onun `float` olup olmadığını kontol ediyor.
- * `is_offer` adında bir parametetre olup olmadığını ve var ise onun `bool` olup olmadığını kontol ediyor.
- * Bunların hepsini en derin JSON modellerinde bile yapacaktır.
-* Bütün veri tiplerini otomatik olarak JSON'a çeviriyor veya tam tersi.
-* Her şeyi dokümanlayıp, çeşitli yerlerde:
- * İnteraktif dokümantasyon sistemleri.
- * Otomatik alıcı kodu üretim sistemlerinde ve çeşitli dillerde.
-* İki ayrı web arayüzüyle direkt olarak interaktif bir dokümantasyon sunuyor.
+ * Eğer `None` olmasa zorunlu bir parametre olacaktı (`PUT` metodunun gövdesinde olduğu gibi).
+* `PUT` isteği için `/items/{item_id}`'nin gövdesini, JSON olarak doğrulayıp okuyacak:
+ * `name` adında zorunlu bir parametre olup olmadığını ve varsa tipinin `str` olup olmadığını kontol edecek.
+ * `price` adında zorunlu bir parametre olup olmadığını ve varsa tipinin `float` olup olmadığını kontol edecek.
+ * `is_offer` adında opsiyonel bir parametre olup olmadığını ve varsa tipinin `float` olup olmadığını kontol edecek.
+ * Bunların hepsi en derin JSON nesnelerinde bile çalışacak.
+* Verilerin JSON'a ve JSON'ın python nesnesine dönüşümü otomatik olarak yapılacak.
+* Her şeyi OpenAPI ile uyumlu bir şekilde otomatik olarak dokümanlayacak ve bunlarda aşağıdaki gibi kullanılabilecek:
+ * Etkileşimli dokümantasyon sistemleri.
+ * Bir çok programlama dili için otomatik istemci kodu üretim sistemleri.
+* İki ayrı etkileşimli dokümantasyon arayüzünü doğrudan sağlayacak.
---
-Henüz yüzeysel bir bakış attık, fakat sen çoktan çalışma mantığını anladın.
+Daha yeni başladık ama çalışma mantığını çoktan anlamış oldunuz.
-Şimdi aşağıdaki satırı değiştirmeyi dene:
+Şimdi aşağıdaki satırı değiştirmeyi deneyin:
```Python
return {"item_name": item.name, "item_id": item_id}
@@ -418,58 +418,57 @@ Henüz yüzeysel bir bakış attık, fakat sen çoktan çalışma mantığını
... "item_price": item.price ...
```
-...şimdi editör desteğinin nasıl veri tiplerini bildiğini ve otomatik tamamladığını gör:
+...ve editörünün veri tiplerini bildiğini ve otomatik tamamladığını göreceksiniz:

-Daha fazla örnek ve özellik için
Tutorial - User Guide sayfasını git.
+Daha fazal özellik içeren, daha eksiksiz bir örnek için
Öğretici - Kullanıcı Rehberi sayfasını ziyaret edebilirsin.
-**Spoiler**: Öğretici - Kullanıcı rehberi şunları içeriyor:
+**Spoiler**: Öğretici - Kullanıcı rehberi şunları içerir:
-* **Parameterlerini** nasıl **headers**, **cookies**, **form fields** ve **files** olarak deklare edebileceğini.
-* `maximum_length` ya da `regex` gibi şeylerle nasıl **doğrulama** yapabileceğini.
-* Çok güçlü ve kullanımı kolay **
Zorunluluk Entegrasyonu** oluşturmayı.
-* Güvenlik ve kimlik doğrulama, **JWT tokenleri**'yle beraber **OAuth2** desteği, ve **HTTP Basic** doğrulaması.
-* İleri seviye fakat ona göre oldukça basit olan **derince oluşturulmuş JSON modelleri** (Pydantic sayesinde).
+* **Parameterlerin**, **headers**, **çerezler**, **form alanları** ve **dosyalar** olarak tanımlanması.
+* `maximum_length` ya da `regex` gibi **doğrulama kısıtlamalarının** nasıl yapılabileceği.
+* Çok güçlü ve kullanımı kolay **
Bağımlılık Enjeksiyonu** sistemi oluşturmayı.
+* Güvenlik ve kimlik doğrulama, **JWT tokenleri** ile **OAuth2** desteği, ve **HTTP Basic** doğrulaması.
+* İleri seviye fakat bir o kadarda basit olan **çok derin JSON modelleri** (Pydantic sayesinde).
+* **GraphQL** entegrasyonu:
Strawberry ve diğer kütüphaneleri kullanarak.
* Diğer ekstra özellikler (Starlette sayesinde):
- * **WebSockets**
- * **GraphQL**
- * `requests` ve `pytest` sayesinde aşırı kolay testler.
+ * **WebSocketler**
+ * HTTPX ve `pytest` sayesinde aşırı kolay testler.
* **CORS**
* **Cookie Sessions**
* ...ve daha fazlası.
## Performans
-Bağımsız TechEmpower kıyaslamaları gösteriyor ki, Uvicorn'la beraber çalışan **FastAPI** uygulamaları
Python'un en hızlı frameworklerinden birisi , sadece Starlette ve Uvicorn'dan daha yavaş ki FastAPI bunların üzerine kurulu.
+Bağımsız TechEmpower kıyaslamaları gösteriyor ki, Uvicorn ile çalıştırılan **FastAPI** uygulamaları
en hızlı Python framework'lerinden birisi, sadece Starlette ve Uvicorn'dan yavaş, ki FastAPI bunların üzerine kurulu bir kütüphanedir.
-Daha fazla bilgi için, bu bölüme bir göz at
Benchmarks.
+Daha fazla bilgi için, bu bölüme bir göz at
Kıyaslamalar.
-## Opsiyonel gereksinimler
+## Opsiyonel Gereksinimler
Pydantic tarafında kullanılan:
-*
ujson
- daha hızlı JSON
"dönüşümü" için.
-*
email_validator
- email doğrulaması için.
+*
email-validator
- email doğrulaması için.
+*
pydantic-settings
- ayar yönetimi için.
+*
pydantic-extra-types
- Pydantic ile birlikte kullanılabilecek ek tipler için.
Starlette tarafında kullanılan:
-*
requests
- Eğer `TestClient` kullanmak istiyorsan gerekli.
-*
aiofiles
- `FileResponse` ya da `StaticFiles` kullanmak istiyorsan gerekli.
-*
jinja2
- Eğer kendine ait template konfigürasyonu oluşturmak istiyorsan gerekli
-*
python-multipart
- Form kullanmak istiyorsan gerekli
("dönüşümü").
+*
httpx
- Eğer `TestClient` yapısını kullanacaksanız gereklidir.
+*
jinja2
- Eğer varsayılan template konfigürasyonunu kullanacaksanız gereklidir.
+*
python-multipart
- Eğer `request.form()` ile form
dönüşümü desteğini kullanacaksanız gereklidir.
*
itsdangerous
- `SessionMiddleware` desteği için gerekli.
*
pyyaml
- `SchemaGenerator` desteği için gerekli (Muhtemelen FastAPI kullanırken ihtiyacınız olmaz).
-*
graphene
- `GraphQLApp` desteği için gerekli.
-*
ujson
- `UJSONResponse` kullanmak istiyorsan gerekli.
Hem FastAPI hem de Starlette tarafından kullanılan:
-*
uvicorn
- oluşturduğumuz uygulamayı bir web sunucusuna servis etmek için gerekli
-*
orjson
- `ORJSONResponse` kullanmak istiyor isen gerekli.
+*
uvicorn
- oluşturduğumuz uygulamayı servis edecek web sunucusu görevini üstlenir.
+*
orjson
- `ORJSONResponse` kullanacaksanız gereklidir.
+*
ujson
- `UJSONResponse` kullanacaksanız gerekli.
Bunların hepsini `pip install fastapi[all]` ile yükleyebilirsin.
## Lisans
-Bu proje, MIT lisansı şartlarına göre lisanslanmıştır.
+Bu proje, MIT lisansı şartları altında lisanslanmıştır.
diff --git a/docs/tr/docs/learn/index.md b/docs/tr/docs/learn/index.md
new file mode 100644
index 000000000..52e3aa54d
--- /dev/null
+++ b/docs/tr/docs/learn/index.md
@@ -0,0 +1,5 @@
+# Öğren
+
+**FastAPI** öğrenmek için giriş bölümleri ve öğreticiler burada yer alıyor.
+
+Burayı, bir **kitap**, bir **kurs**, ve FastAPI öğrenmenin **resmi** ve önerilen yolu olarak düşünülebilirsiniz. 😎
diff --git a/docs/tr/docs/project-generation.md b/docs/tr/docs/project-generation.md
new file mode 100644
index 000000000..c9dc24acc
--- /dev/null
+++ b/docs/tr/docs/project-generation.md
@@ -0,0 +1,84 @@
+# Proje oluşturma - Şablonlar
+
+Başlamak için bir proje oluşturucu kullanabilirsiniz, çünkü sizin için önceden yapılmış birçok başlangıç kurulumu, güvenlik, veritabanı ve temel API endpoinlerini içerir.
+
+Bir proje oluşturucu, her zaman kendi ihtiyaçlarınıza göre güncellemeniz ve uyarlamanız gereken esnek bir kuruluma sahip olacaktır, ancak bu, projeniz için iyi bir başlangıç noktası olabilir.
+
+## Full Stack FastAPI PostgreSQL
+
+GitHub:
https://github.com/tiangolo/full-stack-fastapi-postgresql
+
+### Full Stack FastAPI PostgreSQL - Özellikler
+
+* Full **Docker** entegrasyonu (Docker based).
+* Docker Swarm Mode ile deployment.
+* **Docker Compose** entegrasyonu ve lokal geliştirme için optimizasyon.
+* Uvicorn ve Gunicorn ile **Production ready** Python web server'ı.
+* Python
**FastAPI** backend:
+ * **Hızlı**: **NodeJS** ve **Go** ile eşit, çok yüksek performans (Starlette ve Pydantic'e teşekkürler).
+ * **Sezgisel**: Editor desteğı.
Otomatik tamamlama. Daha az debugging.
+ * **Kolay**: Kolay öğrenip kolay kullanmak için tasarlandı. Daha az döküman okuma daha çok iş.
+ * **Kısa**: Minimum kod tekrarı. Her parametre bildiriminde birden çok özellik.
+ * **Güçlü**: Production-ready. Otomatik interaktif dökümantasyon.
+ * **Standartlara dayalı**: API'ler için açık standartlara dayanır (ve tamamen uyumludur):
OpenAPI ve
JSON Şeması.
+ *
**Birçok diger özelliği** dahili otomatik doğrulama, serialization, interaktif dokümantasyon, OAuth2 JWT token ile authentication, vb.
+* **Güvenli şifreleme** .
+* **JWT token** kimlik doğrulama.
+* **SQLAlchemy** models (Flask dan bağımsızdır. Celery worker'ları ile kullanılabilir).
+* Kullanıcılar için temel başlangıç modeli (gerektiği gibi değiştirin ve kaldırın).
+* **Alembic** migration.
+* **CORS** (Cross Origin Resource Sharing).
+* **Celery** worker'ları ile backend içerisinden seçilen işleri çalıştırabilirsiniz.
+* **Pytest**'e dayalı, Docker ile entegre REST backend testleri ile veritabanından bağımsız olarak tam API etkileşimini test edebilirsiniz. Docker'da çalıştığı için her seferinde sıfırdan yeni bir veri deposu oluşturabilir (böylece ElasticSearch, MongoDB, CouchDB veya ne istersen kullanabilirsin ve sadece API'nin çalışıp çalışmadığını test edebilirsin).
+* Atom Hydrogen veya Visual Studio Code Jupyter gibi uzantılarla uzaktan veya Docker içi geliştirme için **Jupyter Çekirdekleri** ile kolay Python entegrasyonu.
+* **Vue** ile frontend:
+ * Vue CLI ile oluşturulmuş.
+ * Dahili **JWT kimlik doğrulama**.
+ * Dahili Login.
+ * Login sonrası, Kontrol paneli.
+ * Kullanıcı oluşturma ve düzenleme kontrol paneli
+ * Kendi kendine kullanıcı sürümü.
+ * **Vuex**.
+ * **Vue-router**.
+ * **Vuetify** güzel material design kompanentleri için.
+ * **TypeScript**.
+ * **Nginx** tabanlı Docker sunucusu (Vue-router için yapılandırılmış).
+ * Docker ile multi-stage yapı, böylece kodu derlemeniz, kaydetmeniz veya işlemeniz gerekmez.
+ * Derleme zamanında Frontend testi (devre dışı bırakılabilir).
+ * Mümkün olduğu kadar modüler yapılmıştır, bu nedenle kutudan çıktığı gibi çalışır, ancak Vue CLI ile yeniden oluşturabilir veya ihtiyaç duyduğunuz şekilde oluşturabilir ve istediğinizi yeniden kullanabilirsiniz.
+* **PGAdmin** PostgreSQL database admin tool'u, PHPMyAdmin ve MySQL ile kolayca değiştirilebilir.
+* **Flower** ile Celery job'larını monitörleme.
+* **Traefik** ile backend ve frontend arasında yük dengeleme, böylece her ikisini de aynı domain altında, path ile ayrılmış, ancak farklı kapsayıcılar tarafından sunulabilirsiniz.
+* Let's Encrypt **HTTPS** sertifikalarının otomatik oluşturulması dahil olmak üzere Traefik entegrasyonu.
+* GitLab **CI** (sürekli entegrasyon), backend ve frontend testi dahil.
+
+## Full Stack FastAPI Couchbase
+
+GitHub:
https://github.com/tiangolo/full-stack-fastapi-couchbase
+
+⚠️ **UYARI** ⚠️
+
+Sıfırdan bir projeye başlıyorsanız alternatiflerine bakın.
+
+Örneğin,
Full Stack FastAPI PostgreSQL daha iyi bir alternatif olabilir, aktif olarak geliştiriliyor ve kullanılıyor. Ve yeni özellik ve ilerlemelere sahip.
+
+İsterseniz Couchbase tabanlı generator'ı kullanmakta özgürsünüz, hala iyi çalışıyor olmalı ve onunla oluşturulmuş bir projeniz varsa bu da sorun değil (ve muhtemelen zaten ihtiyaçlarınıza göre güncellediniz).
+
+Bununla ilgili daha fazla bilgiyi repo belgelerinde okuyabilirsiniz.
+
+## Full Stack FastAPI MongoDB
+
+... müsaitliğime ve diğer faktörlere bağlı olarak daha sonra gelebilir. 😅 🎉
+
+## Machine Learning modelleri, spaCy ve FastAPI
+
+GitHub:
https://github.com/microsoft/cookiecutter-spacy-fastapi
+
+### Machine Learning modelleri, spaCy ve FastAPI - Features
+
+* **spaCy** NER model entegrasyonu.
+* **Azure Cognitive Search** yerleşik istek biçimi.
+* Uvicorn ve Gunicorn ile **Production ready** Python web server'ı.
+* Dahili **Azure DevOps** Kubernetes (AKS) CI/CD deployment.
+* **Multilingual**, Proje kurulumu sırasında spaCy'nin yerleşik dillerinden birini kolayca seçin.
+* **Esnetilebilir** diğer frameworkler (Pytorch, Tensorflow) ile de çalışır sadece spaCy değil.
diff --git a/docs/tr/docs/python-types.md b/docs/tr/docs/python-types.md
new file mode 100644
index 000000000..b44aa3b9d
--- /dev/null
+++ b/docs/tr/docs/python-types.md
@@ -0,0 +1,313 @@
+# Python Veri Tiplerine Giriş
+
+Python isteğe bağlı olarak "tip belirteçlerini" destekler.
+
+ **"Tip belirteçleri"** bir değişkenin
tipinin belirtilmesine olanak sağlayan özel bir sözdizimidir.
+
+Değişkenlerin tiplerini belirterek editör ve araçlardan daha fazla destek alabilirsiniz.
+
+Bu pythonda tip belirteçleri için **hızlı bir başlangıç / bilgi tazeleme** rehberidir . Bu rehber **FastAPI** kullanmak için gereken minimum konuyu kapsar ki bu da çok az bir miktardır.
+
+**FastAPI' nin** tamamı bu tür tip belirteçleri ile donatılmıştır ve birçok avantaj sağlamaktadır.
+
+**FastAPI** kullanmayacak olsanız bile tür belirteçleri hakkında bilgi edinmenizde fayda var.
+
+/// note | Not
+
+Python uzmanıysanız ve tip belirteçleri ilgili her şeyi zaten biliyorsanız, sonraki bölüme geçin.
+
+///
+
+## Motivasyon
+
+Basit bir örnek ile başlayalım:
+
+{* ../../docs_src/python_types/tutorial001.py *}
+
+
+Programın çıktısı:
+
+```
+John Doe
+```
+
+Fonksiyon sırayla şunları yapar:
+
+* `first_name` ve `last_name` değerlerini alır.
+* `title()` ile değişkenlerin ilk karakterlerini büyütür.
+* Değişkenleri aralarında bir boşlukla beraber
Birleştirir.
+
+{* ../../docs_src/python_types/tutorial001.py hl[2] *}
+
+
+### Düzenle
+
+Bu çok basit bir program.
+
+Ama şimdi sıfırdan yazdığınızı hayal edin.
+
+Bir noktada fonksiyonun tanımına başlayacaktınız, parametreleri hazır hale getirdiniz...
+
+Ama sonra "ilk harfi büyük harfe dönüştüren yöntemi" çağırmanız gerekir.
+
+ `upper` mıydı ? Yoksa `uppercase`' mi? `first_uppercase`? `capitalize`?
+
+Ardından, programcıların en iyi arkadaşı olan otomatik tamamlama ile denediniz.
+
+'first_name', ardından bir nokta ('.') yazıp otomatik tamamlamayı tetiklemek için 'Ctrl+Space' tuşlarına bastınız.
+
+Ancak, ne yazık ki, yararlı hiçbir şey elde edemediniz:
+
+

+
+### Tipleri ekle
+
+Önceki sürümden sadece bir satırı değiştirelim.
+
+Tam olarak bu parçayı, işlevin parametrelerini değiştireceğiz:
+
+```Python
+ first_name, last_name
+```
+
+ve bu hale getireceğiz:
+
+```Python
+ first_name: str, last_name: str
+```
+
+Bu kadar.
+
+İşte bunlar "tip belirteçleri":
+
+{* ../../docs_src/python_types/tutorial002.py hl[1] *}
+
+
+Bu, aşağıdaki gibi varsayılan değerleri bildirmekle aynı şey değildir:
+
+```Python
+ first_name="john", last_name="doe"
+```
+
+Bu tamamen farklı birşey
+
+İki nokta üst üste (`:`) kullanıyoruz , eşittir (`=`) değil.
+
+Normalde tip belirteçleri eklemek, kod üzerinde olacakları değiştirmez.
+
+Şimdi programı sıfırdan birdaha yazdığınızı hayal edin.
+
+Aynı noktada, `Ctrl+Space` ile otomatik tamamlamayı tetiklediniz ve şunu görüyorsunuz:
+
+

+
+Aradığınızı bulana kadar seçenekleri kaydırabilirsiniz:
+
+

+
+## Daha fazla motivasyon
+
+Bu fonksiyon, zaten tür belirteçlerine sahip:
+
+{* ../../docs_src/python_types/tutorial003.py hl[1] *}
+
+
+Editör değişkenlerin tiplerini bildiğinden, yalnızca otomatik tamamlama değil, hata kontrolleri de sağlar:
+
+

+
+Artık `age` değişkenini `str(age)` olarak kullanmanız gerektiğini biliyorsunuz:
+
+{* ../../docs_src/python_types/tutorial004.py hl[2] *}
+
+
+## Tip bildirme
+
+Az önce tip belirteçlerinin en çok kullanıldığı yeri gördünüz.
+
+ **FastAPI**ile çalışırken tip belirteçlerini en çok kullanacağımız yer yine fonksiyonlardır.
+
+### Basit tipler
+
+Yalnızca `str` değil, tüm standart Python tiplerinin bildirebilirsiniz.
+
+Örneğin şunları kullanabilirsiniz:
+
+* `int`
+* `float`
+* `bool`
+* `bytes`
+
+{* ../../docs_src/python_types/tutorial005.py hl[1] *}
+
+
+### Tip parametreleri ile Generic tipler
+
+"dict", "list", "set" ve "tuple" gibi diğer değerleri içerebilen bazı veri yapıları vardır. Ve dahili değerlerinin de tip belirtecleri olabilir.
+
+Bu tipleri ve dahili tpileri bildirmek için standart Python modülünü "typing" kullanabilirsiniz.
+
+Bu tür tip belirteçlerini desteklemek için özel olarak mevcuttur.
+
+#### `List`
+
+Örneğin `str` değerlerden oluşan bir `list` tanımlayalım.
+
+From `typing`, import `List` (büyük harf olan `L` ile):
+
+{* ../../docs_src/python_types/tutorial006.py hl[1] *}
+
+
+Değişkenin tipini yine iki nokta üstüste (`:`) ile belirleyin.
+
+tip olarak `List` kullanın.
+
+Liste, bazı dahili tipleri içeren bir tür olduğundan, bunları köşeli parantez içine alırsınız:
+
+{* ../../docs_src/python_types/tutorial006.py hl[4] *}
+
+
+/// tip | Ipucu
+
+Köşeli parantez içindeki bu dahili tiplere "tip parametreleri" denir.
+
+Bu durumda `str`, `List`e iletilen tür parametresidir.
+
+///
+
+Bunun anlamı şudur: "`items` değişkeni bir `list`tir ve bu listedeki öğelerin her biri bir `str`dir".
+
+Bunu yaparak, düzenleyicinizin listedeki öğeleri işlerken bile destek sağlamasını sağlayabilirsiniz:
+
+

+
+Tip belirteçleri olmadan, bunu başarmak neredeyse imkansızdır.
+
+`item` değişkeninin `items` listesindeki öğelerden biri olduğuna dikkat edin.
+
+Ve yine, editör bunun bir `str` olduğunu biliyor ve bunun için destek sağlıyor.
+
+#### `Tuple` ve `Set`
+
+`Tuple` ve `set`lerin tiplerini bildirmek için de aynısını yapıyoruz:
+
+{* ../../docs_src/python_types/tutorial007.py hl[1,4] *}
+
+
+Bu şu anlama geliyor:
+
+* `items_t` değişkeni sırasıyla `int`, `int`, ve `str` tiplerinden oluşan bir `tuple` türündedir .
+* `items_s` ise her öğesi `bytes` türünde olan bir `set` örneğidir.
+
+#### `Dict`
+
+Bir `dict` tanımlamak için virgülle ayrılmış iki parametre verebilirsiniz.
+
+İlk tip parametresi `dict` değerinin `key` değeri içindir.
+
+İkinci parametre ise `dict` değerinin `value` değeri içindir:
+
+{* ../../docs_src/python_types/tutorial008.py hl[1,4] *}
+
+
+Bu şu anlama gelir:
+
+* `prices` değişkeni `dict` tipindedir:
+ * `dict` değişkeninin `key` değeri `str` tipindedir (herbir item'ın "name" değeri).
+ * `dict` değişkeninin `value` değeri `float` tipindedir (lherbir item'ın "price" değeri).
+
+#### `Optional`
+
+`Optional` bir değişkenin `str`gibi bir tipi olabileceğini ama isteğe bağlı olarak tipinin `None` olabileceğini belirtir:
+
+```Python hl_lines="1 4"
+{!../../docs_src/python_types/tutorial009.py!}
+```
+
+`str` yerine `Optional[str]` kullanmak editorün bu değerin her zaman `str` tipinde değil bazen `None` tipinde de olabileceğini belirtir ve hataları tespit etmemizde yardımcı olur.
+
+#### Generic tipler
+
+Köşeli parantez içinde tip parametreleri alan bu türler, örneğin:
+
+* `List`
+* `Tuple`
+* `Set`
+* `Dict`
+* `Optional`
+* ...and others.
+
+**Generic types** yada **Generics** olarak adlandırılır.
+
+### Tip olarak Sınıflar
+
+Bir değişkenin tipini bir sınıf ile bildirebilirsiniz.
+
+Diyelim ki `name` değerine sahip `Person` sınıfınız var:
+
+{* ../../docs_src/python_types/tutorial010.py hl[1:3] *}
+
+
+Sonra bir değişkeni 'Person' tipinde tanımlayabilirsiniz:
+
+{* ../../docs_src/python_types/tutorial010.py hl[6] *}
+
+
+Ve yine bütün editör desteğini alırsınız:
+
+

+
+## Pydantic modelleri
+
+
Pydantic veri doğrulaması yapmak için bir Python kütüphanesidir.
+
+Verilerin "biçimini" niteliklere sahip sınıflar olarak düzenlersiniz.
+
+Ve her niteliğin bir türü vardır.
+
+Sınıfın bazı değerlerle bir örneğini oluşturursunuz ve değerleri doğrular, bunları uygun türe dönüştürür ve size tüm verileri içeren bir nesne verir.
+
+Ve ortaya çıkan nesne üzerindeki bütün editör desteğini alırsınız.
+
+Resmi Pydantic dokümanlarından alınmıştır:
+
+{* ../../docs_src/python_types/tutorial011.py *}
+
+
+/// info
+
+Daha fazla şey öğrenmek için
Pydantic'i takip edin.
+
+///
+
+**FastAPI** tamamen Pydantic'e dayanmaktadır.
+
+Daha fazlasini görmek için [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}.
+
+## **FastAPI** tip belirteçleri
+
+**FastAPI** birkaç şey yapmak için bu tür tip belirteçlerinden faydalanır.
+
+**FastAPI** ile parametre tiplerini bildirirsiniz ve şunları elde edersiniz:
+
+* **Editor desteği**.
+* **Tip kontrolü**.
+
+...ve **FastAPI** aynı belirteçleri şunlar için de kullanıyor:
+
+* **Gereksinimleri tanımlama**: request path parameters, query parameters, headers, bodies, dependencies, ve benzeri gereksinimlerden
+* **Verileri çevirme**: Gönderilen veri tipinden istenilen veri tipine çevirme.
+* **Verileri doğrulama**: Her gönderilen verinin:
+ * doğrulanması ve geçersiz olduğunda **otomatik hata** oluşturma.
+* OpenAPI kullanarak apinizi **Belgeleyin** :
+ * bu daha sonra otomatik etkileşimli dokümantasyon kullanıcı arayüzü tarafından kullanılır.
+
+Bütün bunlar kulağa soyut gelebilir. Merak etme. Tüm bunları çalışırken göreceksiniz. [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}.
+
+Önemli olan, standart Python türlerini tek bir yerde kullanarak (daha fazla sınıf, dekoratör vb. eklemek yerine), **FastAPI**'nin bizim için işi yapmasını sağlamak.
+
+/// info
+
+Tüm öğreticiyi zaten okuduysanız ve türler hakkında daha fazla bilgi için geri döndüyseniz, iyi bir kaynak:
the "cheat sheet" from `mypy`.
+
+///
diff --git a/docs/tr/docs/resources/index.md b/docs/tr/docs/resources/index.md
new file mode 100644
index 000000000..fc71a9ca1
--- /dev/null
+++ b/docs/tr/docs/resources/index.md
@@ -0,0 +1,3 @@
+# Kaynaklar
+
+Ek kaynaklar, dış bağlantılar, makaleler ve daha fazlası. ✈️
diff --git a/docs/tr/docs/tutorial/cookie-params.md b/docs/tr/docs/tutorial/cookie-params.md
new file mode 100644
index 000000000..f07508c2f
--- /dev/null
+++ b/docs/tr/docs/tutorial/cookie-params.md
@@ -0,0 +1,35 @@
+# Çerez (Cookie) Parametreleri
+
+`Query` (Sorgu) ve `Path` (Yol) parametrelerini tanımladığınız şekilde çerez parametreleri tanımlayabilirsiniz.
+
+## Import `Cookie`
+
+Öncelikle, `Cookie`'yi projenize dahil edin:
+
+{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *}
+
+## `Cookie` Parametrelerini Tanımlayın
+
+Çerez parametrelerini `Path` veya `Query` tanımlaması yapar gibi tanımlayın.
+
+İlk değer varsayılan değerdir; tüm ekstra doğrulama veya belirteç parametrelerini kullanabilirsiniz:
+
+{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *}
+
+/// note | Teknik Detaylar
+
+`Cookie` sınıfı `Path` ve `Query` sınıflarının kardeşidir. Diğerleri gibi `Param` sınıfını miras alan bir sınıftır.
+
+Ancak `fastapi`'dan projenize dahil ettiğiniz `Query`, `Path`, `Cookie` ve diğerleri aslında özel sınıflar döndüren birer fonksiyondur.
+
+///
+
+/// info | Bilgi
+
+Çerez tanımlamak için `Cookie` sınıfını kullanmanız gerekmektedir, aksi taktirde parametreler sorgu parametreleri olarak yorumlanır.
+
+///
+
+## Özet
+
+Çerez tanımlamalarını `Cookie` sınıfını kullanarak `Query` ve `Path` tanımlar gibi tanımlayın.
diff --git a/docs/tr/docs/tutorial/first-steps.md b/docs/tr/docs/tutorial/first-steps.md
new file mode 100644
index 000000000..2d2949b50
--- /dev/null
+++ b/docs/tr/docs/tutorial/first-steps.md
@@ -0,0 +1,335 @@
+# İlk Adımlar
+
+En sade FastAPI dosyası şu şekilde görünür:
+
+{* ../../docs_src/first_steps/tutorial001.py *}
+
+Yukarıdaki içeriği bir `main.py` dosyasına kopyalayalım.
+
+Uygulamayı çalıştıralım:
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [28720]
+INFO: Started server process [28722]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+/// note | Not
+
+`uvicorn main:app` komutunu şu şekilde açıklayabiliriz:
+
+* `main`: dosya olan `main.py` (yani Python "modülü").
+* `app`: ise `main.py` dosyasının içerisinde `app = FastAPI()` satırında oluşturduğumuz `FastAPI` nesnesi.
+* `--reload`: kod değişikliklerinin ardından sunucuyu otomatik olarak yeniden başlatır. Bu parameteyi sadece geliştirme aşamasında kullanmalıyız.
+
+///
+
+Çıktı olarak şöyle bir satır ile karşılaşacaksınız:
+
+```hl_lines="4"
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+Bu satır, yerel makinenizde uygulamanızın çalıştığı bağlantıyı gösterir.
+
+### Kontrol Edelim
+
+Tarayıcınızı açıp
http://127.0.0.1:8000 bağlantısına gidin.
+
+Şu şekilde bir JSON yanıtı ile karşılaşacağız:
+
+```JSON
+{"message": "Hello World"}
+```
+
+### Etkileşimli API Dokümantasyonu
+
+Şimdi
http://127.0.0.1:8000/docs bağlantısını açalım.
+
+
Swagger UI tarafından sağlanan otomatik etkileşimli bir API dokümantasyonu göreceğiz:
+
+
+
+### Alternatif API Dokümantasyonu
+
+Şimdi
http://127.0.0.1:8000/redoc bağlantısını açalım.
+
+
ReDoc tarafından sağlanan otomatik dokümantasyonu göreceğiz:
+
+
+
+### OpenAPI
+
+**FastAPI**, **OpenAPI** standardını kullanarak tüm API'ınızın tamamını tanımlayan bir "şema" oluşturur.
+
+#### "Şema"
+
+"Şema", bir şeyin tanımı veya açıklamasıdır. Geliştirilen koddan ziyade soyut bir açıklamadır.
+
+#### API "Şeması"
+
+Bu durumda,
OpenAPI, API şemasını nasıl tanımlayacağınızı belirten bir şartnamedir.
+
+Bu şema tanımı, API yollarınızla birlikte yollarınızın aldığı olası parametreler gibi tanımlamaları içerir.
+
+#### Veri "Şeması"
+
+"Şema" terimi, JSON içeriği gibi bazı verilerin şeklini de ifade edebilir.
+
+Bu durumda, JSON özellikleri ve sahip oldukları veri türleri gibi anlamlarına gelir.
+
+#### OpenAPI ve JSON Şema
+
+OpenAPI, API'niz için bir API şeması tanımlar. Ve bu şema, JSON veri şemaları standardı olan **JSON Şema** kullanılarak API'niz tarafından gönderilen ve alınan verilerin tanımlarını (veya "şemalarını") içerir.
+
+#### `openapi.json` Dosyasına Göz At
+
+Ham OpenAPI şemasının nasıl göründüğünü merak ediyorsanız, FastAPI otomatik olarak tüm API'ınızın tanımlamalarını içeren bir JSON (şeması) oluşturur.
+
+Bu şemayı direkt olarak
http://127.0.0.1:8000/openapi.json bağlantısından görüntüleyebilirsiniz.
+
+Aşağıdaki gibi başlayan bir JSON ile karşılaşacaksınız:
+
+```JSON
+{
+ "openapi": "3.1.0",
+ "info": {
+ "title": "FastAPI",
+ "version": "0.1.0"
+ },
+ "paths": {
+ "/items/": {
+ "get": {
+ "responses": {
+ "200": {
+ "description": "Successful Response",
+ "content": {
+ "application/json": {
+
+
+
+...
+```
+
+#### OpenAPI Ne İşe Yarar?
+
+OpenAPI şeması, FastAPI projesinde bulunan iki etkileşimli dokümantasyon sistemine güç veren şeydir.
+
+OpenAPI'ya dayalı düzinelerce alternatif etkileşimli dokümantasyon aracı mevcuttur. **FastAPI** ile oluşturulmuş uygulamanıza bu alternatiflerden herhangi birini kolayca ekleyebilirsiniz.
+
+Ayrıca, API'ınızla iletişim kuracak önyüz, mobil veya IoT uygulamaları gibi istemciler için otomatik olarak kod oluşturabilirsiniz.
+
+## Adım Adım Özetleyelim
+
+### Adım 1: `FastAPI`yı Projemize Dahil Edelim
+
+{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
+
+`FastAPI`, API'niz için tüm işlevselliği sağlayan bir Python sınıfıdır.
+
+/// note | Teknik Detaylar
+
+`FastAPI` doğrudan `Starlette`'i miras alan bir sınıftır.
+
+
Starlette'in tüm işlevselliğini `FastAPI` ile de kullanabilirsiniz.
+
+///
+
+### Adım 2: Bir `FastAPI` "Örneği" Oluşturalım
+
+{* ../../docs_src/first_steps/tutorial001.py hl[3] *}
+
+Burada `app` değişkeni `FastAPI` sınıfının bir örneği olacaktır.
+
+Bu, tüm API'yı oluşturmak için ana etkileşim noktası olacaktır.
+
+Bu `app` değişkeni, `uvicorn` komutunda atıfta bulunulan değişkenin ta kendisidir.
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+
+
+Uygulamanızı aşağıdaki gibi oluşturursanız:
+
+{* ../../docs_src/first_steps/tutorial002.py hl[3] *}
+
+Ve bunu `main.py` dosyasına yerleştirirseniz eğer `uvicorn` komutunu şu şekilde çalıştırabilirsiniz:
+
+
+
+```console
+$ uvicorn main:my_awesome_api --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+
+
+### Adım 3: Bir *Yol Operasyonu* Oluşturalım
+
+####
Yol
+
+Burada "yol" bağlantıda bulunan ilk `/` ile başlayan ve sonrasında gelen kısmı ifade eder.
+
+Yani, şu şekilde bir bağlantıda:
+
+```
+https://example.com/items/foo
+```
+
+... yol şöyle olur:
+
+```
+/items/foo
+```
+
+/// info | Bilgi
+
+"Yol" genellikle "
endpoint" veya "
route" olarak adlandırılır.
+
+///
+
+Bir API oluştururken, "yol", "kaynaklar" ile "endişeleri" ayırmanın ana yöntemidir.
+
+#### Operasyonlar
+
+Burada "operasyon" HTTP "metodlarından" birini ifade eder.
+
+Bunlardan biri:
+
+* `POST`
+* `GET`
+* `PUT`
+* `DELETE`
+
+...veya daha az kullanılan diğerleri:
+
+* `OPTIONS`
+* `HEAD`
+* `PATCH`
+* `TRACE`
+
+HTTP protokolünde, bu "metodlardan" birini (veya daha fazlasını) kullanarak her bir yol ile iletişim kurabilirsiniz.
+
+---
+
+API oluştururkan, belirli bir amaca hizmet eden belirli HTTP metodlarını kullanırsınız.
+
+Normalde kullanılan:
+
+* `POST`: veri oluşturmak.
+* `GET`: veri okumak.
+* `PUT`: veriyi güncellemek.
+* `DELETE`: veriyi silmek.
+
+Bu nedenle, OpenAPI'da HTTP metodlarından her birine "operasyon" denir.
+
+Biz de onları "**operasyonlar**" olarak adlandıracağız.
+
+#### Bir *Yol Operasyonu Dekoratörü* Tanımlayalım
+
+{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
+
+`@app.get("/")` dekoratörü, **FastAPI**'a hemen altındaki fonksiyonun aşağıdaki durumlardan sorumlu olduğunu söyler:
+
+*
get
operasyonu ile
+* `/` yoluna gelen istekler
+
+/// info | `@decorator` Bilgisi
+
+Python'da `@something` sözdizimi "
dekoratör" olarak adlandırılır.
+
+Dekoratörler, dekoratif bir şapka gibi (sanırım terim buradan geliyor) fonksiyonların üzerlerine yerleştirilirler.
+
+Bir "dekoratör" hemen altında bulunan fonksiyonu alır ve o fonksiyon ile bazı işlemler gerçekleştirir.
+
+Bizim durumumuzda, kullandığımız dekoratör, **FastAPI**'a altındaki fonksiyonun `/` yoluna gelen `get` metodlu isteklerden sorumlu olduğunu söyler.
+
+Bu bir **yol operasyonu dekoratörüdür**.
+
+///
+
+Ayrıca diğer operasyonları da kullanabilirsiniz:
+
+* `@app.post()`
+* `@app.put()`
+* `@app.delete()`
+
+Daha az kullanılanları da kullanabilirsiniz:
+
+* `@app.options()`
+* `@app.head()`
+* `@app.patch()`
+* `@app.trace()`
+
+/// tip | İpucu
+
+Her işlemi (HTTP metod) istediğiniz gibi kullanmakta özgürsünüz.
+
+**FastAPI** herhangi bir özel amacı veya anlamı olması konusunda ısrarcı olmaz.
+
+Buradaki bilgiler bir gereklilik değil, bir kılavuz olarak sunulmaktadır.
+
+Mesela GraphQL kullanırkan genelde tüm işlemleri yalnızca `POST` operasyonunu kullanarak gerçekleştirirsiniz.
+
+///
+
+### Adım 4: **Yol Operasyonu Fonksiyonunu** Tanımlayın
+
+Aşağıdaki, bizim **yol operasyonu fonksiyonumuzdur**:
+
+* **yol**: `/`
+* **operasyon**: `get`
+* **fonksiyon**: "dekoratör"ün (`@app.get("/")`'in) altındaki fonksiyondur.
+
+{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
+
+Bu bir Python fonksiyonudur.
+
+Bu fonksiyon bir `GET` işlemi kullanılarak "`/`" bağlantısına bir istek geldiğinde **FastAPI** tarafından çağrılır.
+
+Bu durumda bu fonksiyon bir `async` fonksiyondur.
+
+---
+
+Bu fonksiyonu `async def` yerine normal bir fonksiyon olarak da tanımlayabilirsiniz.
+
+{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
+
+/// note | Not
+
+Eğer farkı bilmiyorsanız, [Async: *"Aceleniz mi var?"*](../async.md#in-a-hurry){.internal-link target=_blank} sayfasını kontrol edebilirsiniz.
+
+///
+
+### Adım 5: İçeriği Geri Döndürün
+
+{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
+
+Bir `dict`, `list` veya `str`, `int` gibi tekil değerler döndürebilirsiniz.
+
+Ayrıca, Pydantic modelleri de döndürebilirsiniz (bu konu ileriki aşamalarda irdelenecektir).
+
+Otomatik olarak JSON'a dönüştürülecek (ORM'ler vb. dahil) başka birçok nesne ve model vardır. En beğendiklerinizi kullanmayı deneyin, yüksek ihtimalle destekleniyordur.
+
+## Özet
+
+* `FastAPI`'yı projemize dahil ettik.
+* Bir `app` örneği oluşturduk.
+* Bir **yol operasyonu dekoratörü** (`@app.get("/")` gibi) yazdık.
+* Bir **yol operasyonu fonksiyonu** (`def root(): ...` gibi) yazdık.
+* Geliştirme sunucumuzu (`uvicorn main:app --reload` gibi) çalıştırdık.
diff --git a/docs/tr/docs/tutorial/path-params.md b/docs/tr/docs/tutorial/path-params.md
new file mode 100644
index 000000000..e1707a5d9
--- /dev/null
+++ b/docs/tr/docs/tutorial/path-params.md
@@ -0,0 +1,258 @@
+# Yol Parametreleri
+
+Yol "parametrelerini" veya "değişkenlerini" Python
string biçimlemede kullanılan sözdizimi ile tanımlayabilirsiniz.
+
+{* ../../docs_src/path_params/tutorial001.py hl[6:7] *}
+
+Yol parametresi olan `item_id`'nin değeri, fonksiyonunuza `item_id` argümanı olarak aktarılacaktır.
+
+Eğer bu örneği çalıştırıp
http://127.0.0.1:8000/items/foo sayfasına giderseniz, şöyle bir çıktı ile karşılaşırsınız:
+
+```JSON
+{"item_id":"foo"}
+```
+
+## Tip İçeren Yol Parametreleri
+
+Standart Python tip belirteçlerini kullanarak yol parametresinin tipini fonksiyonun içerisinde tanımlayabilirsiniz.
+
+{* ../../docs_src/path_params/tutorial002.py hl[7] *}
+
+Bu durumda, `item_id` bir `int` olarak tanımlanacaktır.
+
+/// check | Ek bilgi
+
+Bu sayede, fonksiyon içerisinde hata denetimi, kod tamamlama gibi konularda editör desteğine kavuşacaksınız.
+
+///
+
+## Veri
Dönüşümü
+
+Eğer bu örneği çalıştırıp tarayıcınızda
http://127.0.0.1:8000/items/3 sayfasını açarsanız, şöyle bir yanıt ile karşılaşırsınız:
+
+```JSON
+{"item_id":3}
+```
+
+/// check | Ek bilgi
+
+Dikkatinizi çekerim ki, fonksiyonunuzun aldığı (ve döndürdüğü) değer olan `3` bir string `"3"` değil aksine bir Python `int`'idir.
+
+Bu tanımlamayla birlikte, **FastAPI** size otomatik istek
"ayrıştırma" özelliği sağlar.
+
+///
+
+## Veri Doğrulama
+
+Eğer tarayıcınızda
http://127.0.0.1:8000/items/foo sayfasını açarsanız, şuna benzer güzel bir HTTP hatası ile karşılaşırsınız:
+
+```JSON
+{
+ "detail": [
+ {
+ "type": "int_parsing",
+ "loc": [
+ "path",
+ "item_id"
+ ],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "foo",
+ "url": "https://errors.pydantic.dev/2.1/v/int_parsing"
+ }
+ ]
+}
+```
+
+Çünkü burada `item_id` yol parametresi `int` tipinde bir değer beklerken `"foo"` yani `string` tipinde bir değer almıştı.
+
+Aynı hata
http://127.0.0.1:8000/items/4.2 sayfasında olduğu gibi `int` yerine `float` bir değer verseydik de ortaya çıkardı.
+
+/// check | Ek bilgi
+
+Böylece, aynı Python tip tanımlaması ile birlikte, **FastAPI** veri doğrulama özelliği sağlar.
+
+Dikkatinizi çekerim ki, karşılaştığınız hata, doğrulamanın geçersiz olduğu mutlak noktayı da açık bir şekilde belirtiyor.
+
+Bu özellik, API'ınızla iletişime geçen kodu geliştirirken ve ayıklarken inanılmaz derecede yararlı olacaktır.
+
+///
+
+## Dokümantasyon
+
+Ayrıca, tarayıcınızı
http://127.0.0.1:8000/docs adresinde açarsanız, aşağıdaki gibi otomatik ve interaktif bir API dökümantasyonu ile karşılaşırsınız:
+
+

+
+/// check | Ek bilgi
+
+Üstelik, sadece aynı Python tip tanımlaması ile, **FastAPI** size otomatik ve interaktif (Swagger UI ile entegre) bir dokümantasyon sağlar.
+
+Dikkatinizi çekerim ki, yol parametresi integer olarak tanımlanmıştır.
+
+///
+
+## Standartlara Dayalı Avantajlar, Alternatif Dokümantasyon
+
+Oluşturulan şema
OpenAPI standardına uygun olduğu için birçok uyumlu araç mevcuttur.
+
+Bu sayede, **FastAPI**'ın bizzat kendisi
http://127.0.0.1:8000/redoc sayfasından erişebileceğiniz alternatif (ReDoc kullanan) bir API dokümantasyonu sağlar:
+
+

+
+Aynı şekilde, farklı diller için kod türetme araçları da dahil olmak üzere çok sayıda uyumlu araç bulunur.
+
+## Pydantic
+
+Tüm veri doğrulamaları
Pydantic tarafından arka planda gerçekleştirilir, bu sayede tüm avantajlardan faydalanabilirsiniz. Böylece, emin ellerde olduğunuzu hissedebilirsiniz.
+
+Aynı tip tanımlamalarını `str`, `float`, `bool` ve diğer karmaşık veri tipleri ile kullanma imkanınız vardır.
+
+Bunlardan birkaçı, bu eğitimin ileriki bölümlerinde irdelenmiştir.
+
+## Sıralama Önem Arz Eder
+
+*Yol operasyonları* tasarlarken sabit yol barındıran durumlar ile karşılaşabilirsiniz.
+
+Farz edelim ki `/users/me` yolu geçerli kullanıcı hakkında bilgi almak için kullanılıyor olsun.
+
+Benzer şekilde `/users/{user_id}` gibi tanımlanmış ve belirli bir kullanıcı hakkında veri almak için kullanıcının ID bilgisini kullanan bir yolunuz da mevcut olabilir.
+
+*Yol operasyonları* sıralı bir şekilde gözden geçirildiğinden dolayı `/users/me` yolunun `/users/{user_id}` yolundan önce tanımlanmış olmasından emin olmanız gerekmektedir:
+
+{* ../../docs_src/path_params/tutorial003.py hl[6,11] *}
+
+Aksi halde, `/users/{user_id}` yolu `"me"` değerinin `user_id` parametresi için gönderildiğini "düşünerek" `/users/me` ile de eşleşir.
+
+Benzer şekilde, bir yol operasyonunu yeniden tanımlamanız mümkün değildir:
+
+{* ../../docs_src/path_params/tutorial003b.py hl[6,11] *}
+
+Yol, ilk kısım ile eşleştiğinden dolayı her koşulda ilk yol operasyonu kullanılacaktır.
+
+## Ön Tanımlı Değerler
+
+Eğer *yol parametresi* alan bir *yol operasyonunuz* varsa ve alabileceği *yol parametresi* değerlerinin ön tanımlı olmasını istiyorsanız, standart Python
`Enum` tipini kullanabilirsiniz.
+
+### Bir `Enum` Sınıfı Oluşturalım
+
+`Enum` sınıfını projemize dahil edip `str` ile `Enum` sınıflarını miras alan bir alt sınıf yaratalım.
+
+`str` sınıfı miras alındığından dolayı, API dokümanı, değerlerin `string` tipinde olması gerektiğini anlayabilecek ve doğru bir şekilde işlenecektir.
+
+Sonrasında, sınıf içerisinde, mevcut ve geçerli değerler olacak olan sabit değerli özelliklerini oluşturalım:
+
+{* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *}
+
+/// info | Bilgi
+
+3.4 sürümünden beri
enumerationlar (ya da enumlar) Python'da mevcuttur.
+
+///
+
+/// tip | İpucu
+
+Merak ediyorsanız söyleyeyim, "AlexNet", "ResNet" ve "LeNet" isimleri Makine Öğrenmesi
modellerini temsil eder.
+
+///
+
+### Bir *Yol Parametresi* Tanımlayalım
+
+Sonrasında, yarattığımız enum sınıfını (`ModelName`) kullanarak tip belirteci aracılığıyla bir *yol parametresi* oluşturalım:
+
+{* ../../docs_src/path_params/tutorial005.py hl[16] *}
+
+### Dokümana Göz Atalım
+
+*Yol parametresi* için mevcut değerler ön tanımlı olduğundan dolayı, interaktif döküman onları güzel bir şekilde gösterebilir:
+
+

+
+### Python *Enumerationları* ile Çalışmak
+
+*Yol parametresinin* değeri bir *enumeration üyesi* olacaktır.
+
+#### *Enumeration Üyelerini* Karşılaştıralım
+
+Parametreyi, yarattığınız enum olan `ModelName` içerisindeki *enumeration üyesi* ile karşılaştırabilirsiniz:
+
+{* ../../docs_src/path_params/tutorial005.py hl[17] *}
+
+#### *Enumeration Değerini* Edinelim
+
+`model_name.value` veya genel olarak `your_enum_member.value` tanımlarını kullanarak (bu durumda bir `str` olan) gerçek değere ulaşabilirsiniz:
+
+{* ../../docs_src/path_params/tutorial005.py hl[20] *}
+
+/// tip | İpucu
+
+`"lenet"` değerine `ModelName.lenet.value` tanımı ile de ulaşabilirsiniz.
+
+///
+
+#### *Enumeration Üyelerini* Döndürelim
+
+JSON gövdesine (örneğin bir `dict`) gömülü olsalar bile *yol operasyonundaki* *enum üyelerini* döndürebilirsiniz.
+
+Bu üyeler istemciye iletilmeden önce kendilerine karşılık gelen değerlerine (bu durumda string) dönüştürüleceklerdir:
+
+{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *}
+
+İstemci tarafında şuna benzer bir JSON yanıtı ile karşılaşırsınız:
+
+```JSON
+{
+ "model_name": "alexnet",
+ "message": "Deep Learning FTW!"
+}
+```
+
+## Yol İçeren Yol Parametreleri
+
+Farz edelim ki elinizde `/files/{file_path}` isminde bir *yol operasyonu* var.
+
+Fakat `file_path` değerinin `home/johndoe/myfile.txt` gibi bir *yol* barındırmasını istiyorsunuz.
+
+Sonuç olarak, oluşturmak istediğin URL `/files/home/johndoe/myfile.txt` gibi bir şey olacaktır.
+
+### OpenAPI Desteği
+
+Test etmesi ve tanımlaması zor senaryolara sebebiyet vereceğinden dolayı OpenAPI, *yol* barındıran *yol parametrelerini* tanımlayacak bir çözüm sunmuyor.
+
+Ancak bunu, Starlette kütüphanesinin dahili araçlarından birini kullanarak **FastAPI**'da gerçekleştirebilirsiniz.
+
+Parametrenin bir yol içermesi gerektiğini belirten herhangi bir doküman eklemememize rağmen dokümanlar yine de çalışacaktır.
+
+### Yol Dönüştürücü
+
+Direkt olarak Starlette kütüphanesinden gelen bir opsiyon sayesinde aşağıdaki gibi *yol* içeren bir *yol parametresi* bağlantısı tanımlayabilirsiniz:
+
+```
+/files/{file_path:path}
+```
+
+Bu durumda, parametrenin adı `file_path` olacaktır ve son kısım olan `:path` kısmı, parametrenin herhangi bir *yol* ile eşleşmesi gerektiğini belirtecektir.
+
+Böylece şunun gibi bir kullanım yapabilirsiniz:
+
+{* ../../docs_src/path_params/tutorial004.py hl[6] *}
+
+/// tip | İpucu
+
+Parametrenin başında `/home/johndoe/myfile.txt` yolunda olduğu gibi (`/`) işareti ile birlikte kullanmanız gerektiği durumlar olabilir.
+
+Bu durumda, URL, `files` ile `home` arasında iki eğik çizgiye (`//`) sahip olup `/files//home/johndoe/myfile.txt` gibi gözükecektir.
+
+///
+
+## Özet
+
+**FastAPI** ile kısa, sezgisel ve standart Python tip tanımlamaları kullanarak şunları elde edersiniz:
+
+* Editör desteği: hata denetimi, otomatik tamamlama, vb.
+* Veri "
dönüştürme"
+* Veri doğrulama
+* API tanımlamaları ve otomatik dokümantasyon
+
+Ve sadece, bunları bir kez tanımlamanız yeterli.
+
+Diğer frameworkler ile karşılaştırıldığında (ham performans dışında), üstte anlatılan durum muhtemelen **FastAPI**'ın göze çarpan başlıca avantajıdır.
diff --git a/docs/tr/docs/tutorial/query-params.md b/docs/tr/docs/tutorial/query-params.md
new file mode 100644
index 000000000..4aa0a82b1
--- /dev/null
+++ b/docs/tr/docs/tutorial/query-params.md
@@ -0,0 +1,189 @@
+# Sorgu Parametreleri
+
+Fonksiyonda yol parametrelerinin parçası olmayan diğer tanımlamalar otomatik olarak "sorgu" parametresi olarak yorumlanır.
+
+{* ../../docs_src/query_params/tutorial001.py hl[9] *}
+
+Sorgu, bağlantıdaki `?` kısmından sonra gelen ve `&` işareti ile ayrılan anahtar-değer çiftlerinin oluşturduğu bir kümedir.
+
+Örneğin, aşağıdaki bağlantıda:
+
+```
+http://127.0.0.1:8000/items/?skip=0&limit=10
+```
+
+...sorgu parametreleri şunlardır:
+
+* `skip`: değeri `0`'dır
+* `limit`: değeri `10`'dır
+
+Parametreler bağlantının bir parçası oldukları için doğal olarak string olarak değerlendirilirler.
+
+Fakat, Python tipleri ile tanımlandıkları zaman (yukarıdaki örnekte `int` oldukları gibi), parametreler o tiplere dönüştürülür ve o tipler çerçevesinde doğrulanırlar.
+
+Yol parametreleri için geçerli olan her türlü işlem aynı şekilde sorgu parametreleri için de geçerlidir:
+
+* Editör desteği (şüphesiz)
+* Veri "
ayrıştırma"
+* Veri doğrulama
+* Otomatik dokümantasyon
+
+## Varsayılanlar
+
+Sorgu parametreleri, adres yolunun sabit bir parçası olmadıklarından dolayı isteğe bağlı ve varsayılan değere sahip olabilirler.
+
+Yukarıdaki örnekte `skip=0` ve `limit=10` varsayılan değere sahiplerdir.
+
+Yani, aşağıdaki bağlantıya gitmek:
+
+```
+http://127.0.0.1:8000/items/
+```
+
+şu adrese gitmek ile aynı etkiye sahiptir:
+
+```
+http://127.0.0.1:8000/items/?skip=0&limit=10
+```
+
+Ancak, mesela şöyle bir adresi ziyaret ederseniz:
+
+```
+http://127.0.0.1:8000/items/?skip=20
+```
+
+Fonksiyonunuzdaki parametre değerleri aşağıdaki gibi olacaktır:
+
+* `skip=20`: çünkü bağlantıda böyle tanımlandı.
+* `limit=10`: çünkü varsayılan değer buydu.
+
+## İsteğe Bağlı Parametreler
+
+Aynı şekilde, varsayılan değerlerini `None` olarak atayarak isteğe bağlı parametreler tanımlayabilirsiniz:
+
+{* ../../docs_src/query_params/tutorial002_py310.py hl[7] *}
+
+Bu durumda, `q` fonksiyon parametresi isteğe bağlı olacak ve varsayılan değer olarak `None` alacaktır.
+
+/// check | Ek bilgi
+
+Ayrıca, dikkatinizi çekerim ki; **FastAPI**, `item_id` parametresinin bir yol parametresi olduğunu ve `q` parametresinin yol değil bir sorgu parametresi olduğunu fark edecek kadar beceriklidir.
+
+///
+
+## Sorgu Parametresi Tip Dönüşümü
+
+Aşağıda görüldüğü gibi dönüştürülmek üzere `bool` tipleri de tanımlayabilirsiniz:
+
+{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *}
+
+Bu durumda, eğer şu adrese giderseniz:
+
+```
+http://127.0.0.1:8000/items/foo?short=1
+```
+
+veya
+
+```
+http://127.0.0.1:8000/items/foo?short=True
+```
+
+veya
+
+```
+http://127.0.0.1:8000/items/foo?short=true
+```
+
+veya
+
+```
+http://127.0.0.1:8000/items/foo?short=on
+```
+
+veya
+
+```
+http://127.0.0.1:8000/items/foo?short=yes
+```
+
+veya adres, herhangi farklı bir harf varyasyonu içermesi durumuna rağmen (büyük harf, sadece baş harfi büyük kelime, vb.) fonksiyonunuz, `bool` tipli `short` parametresini `True` olarak algılayacaktır. Aksi halde `False` olarak algılanacaktır.
+
+
+## Çoklu Yol ve Sorgu Parametreleri
+
+**FastAPI** neyin ne olduğunu ayırt edebileceğinden dolayı aynı anda birden fazla yol ve sorgu parametresi tanımlayabilirsiniz.
+
+Ve parametreleri, herhangi bir sıraya koymanıza da gerek yoktur.
+
+İsimlerine göre belirleneceklerdir:
+
+{* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *}
+
+## Zorunlu Sorgu Parametreleri
+
+Türü yol olmayan bir parametre (şu ana kadar sadece sorgu parametrelerini gördük) için varsayılan değer tanımlarsanız o parametre zorunlu olmayacaktır.
+
+Parametre için belirli bir değer atamak istemeyip parametrenin sadece isteğe bağlı olmasını istiyorsanız değerini `None` olarak atayabilirsiniz.
+
+Fakat, bir sorgu parametresini zorunlu yapmak istiyorsanız varsayılan bir değer atamamanız yeterli olacaktır:
+
+{* ../../docs_src/query_params/tutorial005.py hl[6:7] *}
+
+Burada `needy` parametresi `str` tipinden oluşan zorunlu bir sorgu parametresidir.
+
+Eğer tarayıcınızda şu bağlantıyı:
+
+```
+http://127.0.0.1:8000/items/foo-item
+```
+
+...`needy` parametresini eklemeden açarsanız şuna benzer bir hata ile karşılaşırsınız:
+
+```JSON
+{
+ "detail": [
+ {
+ "type": "missing",
+ "loc": [
+ "query",
+ "needy"
+ ],
+ "msg": "Field required",
+ "input": null,
+ "url": "https://errors.pydantic.dev/2.1/v/missing"
+ }
+ ]
+}
+```
+
+`needy` zorunlu bir parametre olduğundan dolayı bağlantıda tanımlanması gerekir:
+
+```
+http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
+```
+
+...bu iş görür:
+
+```JSON
+{
+ "item_id": "foo-item",
+ "needy": "sooooneedy"
+}
+```
+
+Ve elbette, bazı parametreleri zorunlu, bazılarını varsayılan değerli ve bazılarını tamamen opsiyonel olarak tanımlayabilirsiniz:
+
+{* ../../docs_src/query_params/tutorial006_py310.py hl[8] *}
+
+Bu durumda, 3 tane sorgu parametresi var olacaktır:
+
+* `needy`, zorunlu bir `str`.
+* `skip`, varsayılan değeri `0` olan bir `int`.
+* `limit`, isteğe bağlı bir `int`.
+
+/// tip | İpucu
+
+Ayrıca, [Yol Parametrelerinde](path-params.md#on-tanml-degerler){.internal-link target=_blank} de kullanıldığı şekilde `Enum` sınıfından faydalanabilirsiniz.
+
+///
diff --git a/docs/tr/docs/tutorial/request-forms.md b/docs/tr/docs/tutorial/request-forms.md
new file mode 100644
index 000000000..e4e04f5f9
--- /dev/null
+++ b/docs/tr/docs/tutorial/request-forms.md
@@ -0,0 +1,69 @@
+# Form Verisi
+
+İstek gövdesinde JSON verisi yerine form alanlarını karşılamanız gerketiğinde `Form` sınıfını kullanabilirsiniz.
+
+/// info | Bilgi
+
+Formları kullanmak için öncelikle
`python-multipart` paketini indirmeniz gerekmektedir.
+
+Örneğin `pip install python-multipart`.
+
+///
+
+## `Form` Sınıfını Projenize Dahil Edin
+
+`Form` sınıfını `fastapi`'den projenize dahil edin:
+
+{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *}
+
+## `Form` Parametrelerini Tanımlayın
+
+Form parametrelerini `Body` veya `Query` için yaptığınız gibi oluşturun:
+
+{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *}
+
+Örneğin, OAuth2 spesifikasyonunun kullanılabileceği ("şifre akışı" olarak adlandırılan) yollardan birinde, form alanları olarak
"username" ve
"password" gönderilmesi gerekir.
+
+Bu
spesifikasyon form alanlarını adlandırırken isimlerinin birebir `username` ve `password` olmasını ve JSON verisi yerine form verisi olarak gönderilmesini gerektirir.
+
+`Form` sınıfıyla tanımlama yaparken `Body`, `Query`, `Path` ve `Cookie` sınıflarında kullandığınız aynı validasyon, örnekler, isimlendirme (örneğin `username` yerine `user-name` kullanımı) ve daha fazla konfigurasyonu kullanabilirsiniz.
+
+/// info | Bilgi
+
+`Form` doğrudan `Body` sınıfını miras alan bir sınıftır.
+
+///
+
+/// tip | İpucu
+
+Form gövdelerini tanımlamak için `Form` sınıfını kullanmanız gerekir; çünkü bu olmadan parametreler sorgu parametreleri veya gövde (JSON) parametreleri olarak yorumlanır.
+
+///
+
+## "Form Alanları" Hakkında
+
+HTML formlarının (`
`) verileri sunucuya gönderirken JSON'dan farklı özel bir kodlama kullanır.
+
+**FastAPI** bu verilerin JSON yerine doğru şekilde okunmasını sağlayacaktır.
+
+/// note | Teknik Detaylar
+
+Form verileri normalde `application/x-www-form-urlencoded` medya tipiyle kodlanır.
+
+Ancak form içerisinde dosyalar yer aldığında `multipart/form-data` olarak kodlanır. Bir sonraki bölümde dosyaların işlenmesi hakkında bilgi edineceksiniz.
+
+Form kodlama türleri ve form alanları hakkında daha fazla bilgi edinmek istiyorsanız
MDN web docs for POST
sayfasını ziyaret edebilirsiniz.
+
+///
+
+/// warning | Uyarı
+
+*Yol operasyonları* içerisinde birden fazla `Form` parametresi tanımlayabilirsiniz ancak bunlarla birlikte JSON verisi kabul eden `Body` alanları tanımlayamazsınız çünkü bu durumda istek gövdesi `application/json` yerine `application/x-www-form-urlencoded` ile kodlanmış olur.
+
+Bu **FastAPI**'ın getirdiği bir kısıtlama değildir, HTTP protokolünün bir parçasıdır.
+
+///
+
+## Özet
+
+Form verisi girdi parametreleri tanımlamak için `Form` sınıfını kullanın.
diff --git a/docs/tr/docs/tutorial/static-files.md b/docs/tr/docs/tutorial/static-files.md
new file mode 100644
index 000000000..db30f13bc
--- /dev/null
+++ b/docs/tr/docs/tutorial/static-files.md
@@ -0,0 +1,40 @@
+# Statik Dosyalar
+
+`StaticFiles`'ı kullanarak statik dosyaları bir yol altında sunabilirsiniz.
+
+## `StaticFiles` Kullanımı
+
+* `StaticFiles` sınıfını projenize dahil edin.
+* Bir `StaticFiles()` örneğini belirli bir yola bağlayın.
+
+{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
+
+/// note | Teknik Detaylar
+
+Projenize dahil etmek için `from starlette.staticfiles import StaticFiles` kullanabilirsiniz.
+
+**FastAPI**, geliştiricilere kolaylık sağlamak amacıyla `starlette.staticfiles`'ı `fastapi.staticfiles` olarak sağlar. Ancak `StaticFiles` sınıfı aslında doğrudan Starlette'den gelir.
+
+///
+
+### Bağlama (Mounting) Nedir?
+
+"Bağlamak", belirli bir yola tamamen "bağımsız" bir uygulama eklemek anlamına gelir ve ardından tüm alt yollara gelen istekler bu uygulama tarafından işlenir.
+
+Bu, bir `APIRouter` kullanmaktan farklıdır çünkü bağlanmış bir uygulama tamamen bağımsızdır. Ana uygulamanızın OpenAPI ve dokümanlar, bağlanmış uygulamadan hiçbir şey içermez, vb.
+
+[Advanced User Guide](../advanced/index.md){.internal-link target=_blank} bölümünde daha fazla bilgi edinebilirsiniz.
+
+## Detaylar
+
+`"/static"` ifadesi, bu "alt uygulamanın" "bağlanacağı" alt yolu belirtir. Bu nedenle, `"/static"` ile başlayan her yol, bu uygulama tarafından işlenir.
+
+`directory="static"` ifadesi, statik dosyalarınızı içeren dizinin adını belirtir.
+
+`name="static"` ifadesi, alt uygulamanın **FastAPI** tarafından kullanılacak ismini belirtir.
+
+Bu parametrelerin hepsi "`static`"den farklı olabilir, bunları kendi uygulamanızın ihtiyaçlarına göre belirleyebilirsiniz.
+
+## Daha Fazla Bilgi
+
+Daha fazla detay ve seçenek için
Starlette'in Statik Dosyalar hakkındaki dokümantasyonunu incelleyin.
diff --git a/docs/tr/mkdocs.yml b/docs/tr/mkdocs.yml
index 6fe2b0b62..de18856f4 100644
--- a/docs/tr/mkdocs.yml
+++ b/docs/tr/mkdocs.yml
@@ -1,130 +1 @@
-site_name: FastAPI
-site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
-site_url: https://fastapi.tiangolo.com/tr/
-theme:
- name: material
- custom_dir: overrides
- palette:
- - scheme: default
- primary: teal
- accent: amber
- toggle:
- icon: material/lightbulb
- name: Switch to light mode
- - scheme: slate
- primary: teal
- accent: amber
- toggle:
- icon: material/lightbulb-outline
- name: Switch to dark mode
- features:
- - search.suggest
- - search.highlight
- - content.tabs.link
- icon:
- repo: fontawesome/brands/github-alt
- logo: https://fastapi.tiangolo.com/img/icon-white.svg
- favicon: https://fastapi.tiangolo.com/img/favicon.png
- language: tr
-repo_name: tiangolo/fastapi
-repo_url: https://github.com/tiangolo/fastapi
-edit_uri: ''
-google_analytics:
-- UA-133183413-1
-- auto
-plugins:
-- search
-- markdownextradata:
- data: data
-nav:
-- FastAPI: index.md
-- Languages:
- - en: /
- - az: /az/
- - de: /de/
- - es: /es/
- - fr: /fr/
- - id: /id/
- - it: /it/
- - ja: /ja/
- - ko: /ko/
- - pl: /pl/
- - pt: /pt/
- - ru: /ru/
- - sq: /sq/
- - tr: /tr/
- - uk: /uk/
- - zh: /zh/
-- features.md
-- fastapi-people.md
-markdown_extensions:
-- toc:
- permalink: true
-- markdown.extensions.codehilite:
- guess_lang: false
-- mdx_include:
- base_path: docs
-- admonition
-- codehilite
-- extra
-- pymdownx.superfences:
- custom_fences:
- - name: mermaid
- class: mermaid
- format: !!python/name:pymdownx.superfences.fence_code_format ''
-- pymdownx.tabbed
-extra:
- social:
- - icon: fontawesome/brands/github-alt
- link: https://github.com/tiangolo/fastapi
- - icon: fontawesome/brands/discord
- link: https://discord.gg/VQjSZaeJmf
- - icon: fontawesome/brands/twitter
- link: https://twitter.com/fastapi
- - icon: fontawesome/brands/linkedin
- link: https://www.linkedin.com/in/tiangolo
- - icon: fontawesome/brands/dev
- link: https://dev.to/tiangolo
- - icon: fontawesome/brands/medium
- link: https://medium.com/@tiangolo
- - icon: fontawesome/solid/globe
- link: https://tiangolo.com
- alternate:
- - link: /
- name: en - English
- - link: /az/
- name: az
- - link: /de/
- name: de
- - link: /es/
- name: es - español
- - link: /fr/
- name: fr - français
- - link: /id/
- name: id
- - link: /it/
- name: it - italiano
- - link: /ja/
- name: ja - 日本語
- - link: /ko/
- name: ko - 한국어
- - link: /pl/
- name: pl
- - link: /pt/
- name: pt - português
- - link: /ru/
- name: ru - русский язык
- - link: /sq/
- name: sq - shqip
- - link: /tr/
- name: tr - Türkçe
- - link: /uk/
- name: uk - українська мова
- - link: /zh/
- name: zh - 汉语
-extra_css:
-- https://fastapi.tiangolo.com/css/termynal.css
-- https://fastapi.tiangolo.com/css/custom.css
-extra_javascript:
-- https://fastapi.tiangolo.com/js/termynal.js
-- https://fastapi.tiangolo.com/js/custom.js
+INHERIT: ../en/mkdocs.yml
diff --git a/docs/uk/docs/alternatives.md b/docs/uk/docs/alternatives.md
new file mode 100644
index 000000000..1acbe237a
--- /dev/null
+++ b/docs/uk/docs/alternatives.md
@@ -0,0 +1,483 @@
+# Альтернативи, натхнення та порівняння
+
+Що надихнуло на створення **FastAPI**, який він у порінянні з іншими альтернативами та чого він у них навчився.
+
+## Вступ
+
+**FastAPI** не існувало б, якби не попередні роботи інших.
+
+Раніше було створено багато інструментів, які надихнули на його створення.
+
+Я кілька років уникав створення нового фреймворку. Спочатку я спробував вирішити всі функції, охоплені **FastAPI**, використовуючи багато різних фреймворків, плагінів та інструментів.
+
+Але в якийсь момент не було іншого виходу, окрім створення чогось, що надавало б усі ці функції, взявши найкращі ідеї з попередніх інструментів і поєднавши їх найкращим чином, використовуючи мовні функції, які навіть не були доступні раніше (Python 3.6+ підказки типів).
+
+## Попередні інструменти
+
+###
Django
+
+Це найпопулярніший фреймворк Python, який користується широкою довірою. Він використовується для створення таких систем, як Instagram.
+
+Він відносно тісно пов’язаний з реляційними базами даних (наприклад, MySQL або PostgreSQL), тому мати базу даних NoSQL (наприклад, Couchbase, MongoDB, Cassandra тощо) як основний механізм зберігання не дуже просто.
+
+Він був створений для створення HTML у серверній частині, а не для створення API, які використовуються сучасним інтерфейсом (як-от React, Vue.js і Angular) або іншими системами (як-от
IoT пристрої), які спілкуються з ним.
+
+###
Django REST Framework
+
+Фреймворк Django REST був створений як гнучкий інструментарій для створення веб-інтерфейсів API використовуючи Django в основі, щоб покращити його можливості API.
+
+Його використовують багато компаній, включаючи Mozilla, Red Hat і Eventbrite.
+
+Це був один із перших прикладів **автоматичної документації API**, і саме це була одна з перших ідей, яка надихнула на «пошук» **FastAPI**.
+
+/// note | Примітка
+
+Django REST Framework створив Том Крісті. Той самий творець Starlette і Uvicorn, на яких базується **FastAPI**.
+
+///
+
+/// check | Надихнуло **FastAPI** на
+
+Мати автоматичний веб-інтерфейс документації API.
+
+///
+
+###
Flask
+
+Flask — це «мікрофреймворк», він не включає інтеграцію бази даних, а також багато речей, які за замовчуванням є в Django.
+
+Ця простота та гнучкість дозволяють використовувати бази даних NoSQL як основну систему зберігання даних.
+
+Оскільки він дуже простий, він порівняно легкий та інтуїтивний для освоєння, хоча в деяких моментах документація стає дещо технічною.
+
+Він також зазвичай використовується для інших програм, яким не обов’язково потрібна база даних, керування користувачами або будь-яка з багатьох функцій, які є попередньо вбудованими в Django. Хоча багато з цих функцій можна додати за допомогою плагінів.
+
+Відокремлення частин було ключовою особливістю, яку я хотів зберегти, при цьому залишаючись «мікрофреймворком», який можна розширити, щоб охопити саме те, що потрібно.
+
+Враховуючи простоту Flask, він здавався хорошим підходом для створення API. Наступним, що знайшов, був «Django REST Framework» для Flask.
+
+/// check | Надихнуло **FastAPI** на
+
+Бути мікрофреймоворком. Зробити легким комбінування та поєднання необхідних інструментів та частин.
+
+ Мати просту та легку у використанні систему маршрутизації.
+
+///
+
+###
Requests
+
+**FastAPI** насправді не є альтернативою **Requests**. Сфера їх застосування дуже різна.
+
+Насправді цілком звична річ використовувати Requests *всередині* програми FastAPI.
+
+Але все ж FastAPI черпав натхнення з Requests.
+
+**Requests** — це бібліотека для *взаємодії* з API (як клієнт), а **FastAPI** — це бібліотека для *створення* API (як сервер).
+
+Вони більш-менш знаходяться на протилежних кінцях, доповнюючи одна одну.
+
+Requests мають дуже простий та інтуїтивно зрозумілий дизайн, дуже простий у використанні, з розумними параметрами за замовчуванням. Але в той же час він дуже потужний і налаштовується.
+
+Ось чому, як сказано на офіційному сайті:
+
+> Requests є одним із найбільш завантажуваних пакетів Python усіх часів
+
+Використовувати його дуже просто. Наприклад, щоб виконати запит `GET`, ви повинні написати:
+
+```Python
+response = requests.get("http://example.com/some/url")
+```
+
+Відповідна операція *роуту* API FastAPI може виглядати так:
+
+```Python hl_lines="1"
+@app.get("/some/url")
+def read_url():
+ return {"message": "Hello World"}
+```
+
+Зверніть увагу на схожість у `requests.get(...)` і `@app.get(...)`.
+
+/// check | Надихнуло **FastAPI** на
+
+* Майте простий та інтуїтивно зрозумілий API.
+ * Використовуйте імена (операції) методів HTTP безпосередньо, простим та інтуїтивно зрозумілим способом.
+ * Розумні параметри за замовчуванням, але потужні налаштування.
+
+///
+
+###
Swagger /
OpenAPI
+
+Головною функцією, яку я хотів від Django REST Framework, була автоматична API документація.
+
+Потім я виявив, що існує стандарт для документування API з використанням JSON (або YAML, розширення JSON) під назвою Swagger.
+
+І вже був створений веб-інтерфейс користувача для Swagger API. Отже, можливість генерувати документацію Swagger для API дозволить використовувати цей веб-інтерфейс автоматично.
+
+У якийсь момент Swagger було передано Linux Foundation, щоб перейменувати його на OpenAPI.
+
+Тому, коли говорять про версію 2.0, прийнято говорити «Swagger», а про версію 3+ «OpenAPI».
+
+/// check | Надихнуло **FastAPI** на
+
+Прийняти і використовувати відкритий стандарт для специфікацій API замість спеціальної схеми.
+
+ Інтегрувати інструменти інтерфейсу на основі стандартів:
+
+ *
Інтерфейс Swagger
+ *
ReDoc
+
+ Ці два було обрано через те, що вони досить популярні та стабільні, але, виконавши швидкий пошук, ви можете знайти десятки додаткових альтернативних інтерфейсів для OpenAPI (які можна використовувати з **FastAPI**).
+
+///
+
+### Фреймворки REST для Flask
+
+Існує кілька фреймворків Flask REST, але, витративши час і роботу на їх дослідження, я виявив, що багато з них припинено або залишено, з кількома постійними проблемами, які зробили їх непридатними.
+
+###
Marshmallow
+
+Однією з головних функцій, необхідних для систем API, є "
серіалізація", яка бере дані з коду (Python) і перетворює їх на щось, що можна надіслати через мережу. Наприклад, перетворення об’єкта, що містить дані з бази даних, на об’єкт JSON. Перетворення об’єктів `datetime` на строки тощо.
+
+Іншою важливою функцією, необхідною для API, є перевірка даних, яка забезпечує дійсність даних за певними параметрами. Наприклад, що деяке поле є `int`, а не деяка випадкова строка. Це особливо корисно для вхідних даних.
+
+Без системи перевірки даних вам довелося б виконувати всі перевірки вручну, у коді.
+
+Marshmallow створено для забезпечення цих функцій. Це чудова бібліотека, і я часто нею користувався раніше.
+
+Але він був створений до того, як існували підказки типу Python. Отже, щоб визначити кожну
схему, вам потрібно використовувати спеціальні утиліти та класи, надані Marshmallow.
+
+/// check | Надихнуло **FastAPI** на
+
+Використовувати код для автоматичного визначення "схем", які надають типи даних і перевірку.
+
+///
+
+###
Webargs
+
+Іншою важливою функцією, необхідною для API, є
аналіз даних із вхідних запитів.
+
+Webargs — це інструмент, створений, щоб забезпечити це поверх кількох фреймворків, включаючи Flask.
+
+Він використовує Marshmallow в основі для перевірки даних. І створений тими ж розробниками.
+
+Це чудовий інструмент, і я також часто використовував його, перш ніж створити **FastAPI**.
+
+/// info | Інформація
+
+Webargs був створений тими ж розробниками Marshmallow.
+
+///
+
+/// check | Надихнуло **FastAPI** на
+
+Мати автоматичну перевірку даних вхідного запиту.
+
+///
+
+###
APISpec
+
+Marshmallow і Webargs забезпечують перевірку, аналіз і серіалізацію як плагіни.
+
+Але документація досі відсутня. Потім було створено APISpec.
+
+Це плагін для багатьох фреймворків (також є плагін для Starlette).
+
+Принцип роботи полягає в тому, що ви пишете визначення схеми, використовуючи формат YAML, у docstring кожної функції, що обробляє маршрут.
+
+І він генерує схеми OpenAPI.
+
+Так це працює у Flask, Starlette, Responder тощо.
+
+Але потім ми знову маємо проблему наявності мікросинтаксису всередині Python строки (великий YAML).
+
+Редактор тут нічим не може допомогти. І якщо ми змінимо параметри чи схеми Marshmallow і забудемо також змінити цю строку документа YAML, згенерована схема буде застарілою.
+
+/// info | Інформація
+
+APISpec був створений тими ж розробниками Marshmallow.
+
+///
+
+/// check | Надихнуло **FastAPI** на
+
+Підтримувати відкритий стандарт API, OpenAPI.
+
+///
+
+###
Flask-apispec
+
+Це плагін Flask, який об’єднує Webargs, Marshmallow і APISpec.
+
+Він використовує інформацію з Webargs і Marshmallow для автоматичного створення схем OpenAPI за допомогою APISpec.
+
+Це чудовий інструмент, дуже недооцінений. Він має бути набагато популярнішим, ніж багато плагінів Flask. Це може бути пов’язано з тим, що його документація надто стисла й абстрактна.
+
+Це вирішило необхідність писати YAML (інший синтаксис) всередині рядків документів Python.
+
+Ця комбінація Flask, Flask-apispec із Marshmallow і Webargs була моїм улюбленим бекенд-стеком до створення **FastAPI**.
+
+Їі використання призвело до створення кількох генераторів повного стека Flask. Це основний стек, який я (та кілька зовнішніх команд) використовував досі:
+
+*
https://github.com/tiangolo/full-stack
+*
https://github.com/tiangolo/full-stack-flask-couchbase
+*
https://github.com/tiangolo/full-stack-flask-couchdb
+
+І ці самі генератори повного стеку були основою [**FastAPI** генераторів проектів](project-generation.md){.internal-link target=_blank}.
+
+/// info | Інформація
+
+Flask-apispec був створений тими ж розробниками Marshmallow.
+
+///
+
+/// check | Надихнуло **FastAPI** на
+
+Створення схеми OpenAPI автоматично з того самого коду, який визначає серіалізацію та перевірку.
+
+///
+
+###
NestJS (та
Angular)
+
+Це навіть не Python, NestJS — це фреймворк NodeJS JavaScript (TypeScript), натхненний Angular.
+
+Це досягає чогось подібного до того, що можна зробити з Flask-apispec.
+
+Він має інтегровану систему впровадження залежностей, натхненну Angular two. Він потребує попередньої реєстрації «injectables» (як і всі інші системи впровадження залежностей, які я знаю), тому це збільшує багатослівність та повторення коду.
+
+Оскільки параметри описані за допомогою типів TypeScript (подібно до підказок типу Python), підтримка редактора досить хороша.
+
+Але оскільки дані TypeScript не зберігаються після компіляції в JavaScript, вони не можуть покладатися на типи для визначення перевірки, серіалізації та документації одночасно. Через це та деякі дизайнерські рішення, щоб отримати перевірку, серіалізацію та автоматичну генерацію схеми, потрібно додати декоратори в багатьох місцях. Таким чином код стає досить багатослівним.
+
+Він не дуже добре обробляє вкладені моделі. Отже, якщо тіло JSON у запиті є об’єктом JSON із внутрішніми полями, які, у свою чергу, є вкладеними об’єктами JSON, його неможливо належним чином задокументувати та перевірити.
+
+/// check | Надихнуло **FastAPI** на
+
+Використовувати типи Python, щоб мати чудову підтримку редактора.
+
+ Мати потужну систему впровадження залежностей. Знайдіть спосіб звести до мінімуму повторення коду.
+
+///
+
+###
Sanic
+
+Це був один із перших надзвичайно швидких фреймворків Python на основі `asyncio`. Він був дуже схожий на Flask.
+
+/// note | Технічні деталі
+
+Він використовував
`uvloop` замість стандартного циклу Python `asyncio`. Ось що зробило його таким швидким.
+
+ Це явно надихнуло Uvicorn і Starlette, які зараз швидші за Sanic у відкритих тестах.
+
+///
+
+/// check | Надихнуло **FastAPI** на
+
+Знайти спосіб отримати божевільну продуктивність.
+
+ Ось чому **FastAPI** базується на Starlette, оскільки це найшвидша доступна структура (перевірена тестами сторонніх розробників).
+
+///
+
+###
Falcon
+
+Falcon — ще один високопродуктивний фреймворк Python, він розроблений як мінімальний і працює як основа інших фреймворків, таких як Hug.
+
+Він розроблений таким чином, щоб мати функції, які отримують два параметри, один «запит» і один «відповідь». Потім ви «читаєте» частини запиту та «записуєте» частини у відповідь. Через такий дизайн неможливо оголосити параметри запиту та тіла за допомогою стандартних підказок типу Python як параметри функції.
+
+Таким чином, перевірка даних, серіалізація та документація повинні виконуватися в коді, а не автоматично. Або вони повинні бути реалізовані як фреймворк поверх Falcon, як Hug. Така сама відмінність спостерігається в інших фреймворках, натхненних дизайном Falcon, що мають один об’єкт запиту та один об’єкт відповіді як параметри.
+
+/// check | Надихнуло **FastAPI** на
+
+Знайти способи отримати чудову продуктивність.
+
+ Разом із Hug (оскільки Hug базується на Falcon) надихнув **FastAPI** оголосити параметр `response` у функціях.
+
+ Хоча у FastAPI це необов’язково, і використовується в основному для встановлення заголовків, файлів cookie та альтернативних кодів стану.
+
+///
+
+###
Molten
+
+Я відкрив для себе Molten на перших етапах створення **FastAPI**. І він має досить схожі ідеї:
+
+* Базується на підказках типу Python.
+* Перевірка та документація цих типів.
+* Система впровадження залежностей.
+
+Він не використовує перевірку даних, серіалізацію та бібліотеку документації сторонніх розробників, як Pydantic, він має свою власну. Таким чином, ці визначення типів даних не можна було б використовувати повторно так легко.
+
+Це вимагає трохи більш докладних конфігурацій. І оскільки він заснований на WSGI (замість ASGI), він не призначений для використання високопродуктивних інструментів, таких як Uvicorn, Starlette і Sanic.
+
+Система впровадження залежностей вимагає попередньої реєстрації залежностей, і залежності вирішуються на основі оголошених типів. Отже, неможливо оголосити більше ніж один «компонент», який надає певний тип.
+
+Маршрути оголошуються в одному місці з використанням функцій, оголошених в інших місцях (замість використання декораторів, які можна розмістити безпосередньо поверх функції, яка обробляє кінцеву точку). Це ближче до того, як це робить Django, ніж до Flask (і Starlette). Він розділяє в коді речі, які відносно тісно пов’язані.
+
+/// check | Надихнуло **FastAPI** на
+
+Визначити додаткові перевірки для типів даних, використовуючи значення "за замовчуванням" атрибутів моделі. Це покращує підтримку редактора, а раніше вона була недоступна в Pydantic.
+
+ Це фактично надихнуло оновити частини Pydantic, щоб підтримувати той самий стиль оголошення перевірки (всі ці функції вже доступні в Pydantic).
+
+///
+
+###
Hug
+
+Hug був одним із перших фреймворків, який реалізував оголошення типів параметрів API за допомогою підказок типу Python. Це була чудова ідея, яка надихнула інші інструменти зробити те саме.
+
+Він використовував спеціальні типи у своїх оголошеннях замість стандартних типів Python, але це все одно був величезний крок вперед.
+
+Це також був один із перших фреймворків, який генерував спеціальну схему, що оголошувала весь API у JSON.
+
+Він не базувався на таких стандартах, як OpenAPI та JSON Schema. Тому було б непросто інтегрувати його з іншими інструментами, як-от Swagger UI. Але знову ж таки, це була дуже інноваційна ідея.
+
+Він має цікаву незвичайну функцію: використовуючи ту саму структуру, можна створювати API, а також CLI.
+
+Оскільки він заснований на попередньому стандарті для синхронних веб-фреймворків Python (WSGI), він не може працювати з Websockets та іншими речами, хоча він також має високу продуктивність.
+
+/// info | Інформація
+
+Hug створив Тімоті Крослі, той самий творець
`isort`, чудовий інструмент для автоматичного сортування імпорту у файлах Python.
+
+///
+
+/// check | Надихнуло **FastAPI** на
+
+Hug надихнув частину APIStar і був одним із найбільш перспективних інструментів, поряд із APIStar.
+
+ Hug надихнув **FastAPI** на використання підказок типу Python для оголошення параметрів і автоматичного створення схеми, що визначає API.
+
+ Hug надихнув **FastAPI** оголосити параметр `response` у функціях для встановлення заголовків і файлів cookie.
+
+///
+
+###
APIStar (<= 0,5)
+
+Безпосередньо перед тим, як вирішити створити **FastAPI**, я знайшов сервер **APIStar**. Він мав майже все, що я шукав, і мав чудовий дизайн.
+
+Це була одна з перших реалізацій фреймворку, що використовує підказки типу Python для оголошення параметрів і запитів, яку я коли-небудь бачив (до NestJS і Molten). Я знайшов його більш-менш одночасно з Hug. Але APIStar використовував стандарт OpenAPI.
+
+Він мав автоматичну перевірку даних, серіалізацію даних і генерацію схеми OpenAPI на основі підказок того самого типу в кількох місцях.
+
+Визначення схеми тіла не використовували ті самі підказки типу Python, як Pydantic, воно було трохи схоже на Marshmallow, тому підтримка редактора була б не такою хорошою, але все ж APIStar був найкращим доступним варіантом.
+
+Він мав найкращі показники продуктивності на той час (перевершив лише Starlette).
+
+Спочатку він не мав автоматичного веб-інтерфейсу документації API, але я знав, що можу додати до нього інтерфейс користувача Swagger.
+
+Він мав систему введення залежностей. Він вимагав попередньої реєстрації компонентів, як і інші інструменти, розглянуті вище. Але все одно це була чудова функція.
+
+Я ніколи не міг використовувати його в повноцінному проекті, оскільки він не мав інтеграції безпеки, тому я не міг замінити всі функції, які мав, генераторами повного стеку на основі Flask-apispec. У моїх невиконаних проектах я мав створити запит на вилучення, додавши цю функцію.
+
+Але потім фокус проекту змінився.
+
+Це вже не був веб-фреймворк API, оскільки творцю потрібно було зосередитися на Starlette.
+
+Тепер APIStar — це набір інструментів для перевірки специфікацій OpenAPI, а не веб-фреймворк.
+
+/// info | Інформація
+
+APIStar створив Том Крісті. Той самий хлопець, який створив:
+
+ * Django REST Framework
+ * Starlette (на якому базується **FastAPI**)
+ * Uvicorn (використовується Starlette і **FastAPI**)
+
+///
+
+/// check | Надихнуло **FastAPI** на
+
+Існувати.
+
+ Ідею оголошення кількох речей (перевірки даних, серіалізації та документації) за допомогою тих самих типів Python, які в той же час забезпечували чудову підтримку редактора, я вважав геніальною ідеєю.
+
+ І після тривалого пошуку подібної структури та тестування багатьох різних альтернатив, APIStar став найкращим доступним варіантом.
+
+ Потім APIStar перестав існувати як сервер, і було створено Starlette, який став новою кращою основою для такої системи. Це стало останнім джерелом натхнення для створення **FastAPI**. Я вважаю **FastAPI** «духовним спадкоємцем» APIStar, удосконалюючи та розширюючи функції, систему введення тексту та інші частини на основі досвіду, отриманого від усіх цих попередніх інструментів.
+
+///
+
+## Використовується **FastAPI**
+
+###
Pydantic
+
+Pydantic — це бібліотека для визначення перевірки даних, серіалізації та документації (за допомогою схеми JSON) на основі підказок типу Python.
+
+Це робить його надзвичайно інтуїтивним.
+
+Його можна порівняти з Marshmallow. Хоча він швидший за Marshmallow у тестах. Оскільки він базується на тих самих підказках типу Python, підтримка редактора чудова.
+
+/// check | **FastAPI** використовує його для
+
+Виконання перевірки всіх даних, серіалізації даних і автоматичної документацію моделі (на основі схеми JSON).
+
+ Потім **FastAPI** бере ці дані схеми JSON і розміщує їх у OpenAPI, окремо від усіх інших речей, які він робить.
+
+///
+
+###
Starlette
+
+Starlette — це легкий фреймворк/набір інструментів
ASGI, який ідеально підходить для створення високопродуктивних asyncio сервісів.
+
+Він дуже простий та інтуїтивно зрозумілий. Його розроблено таким чином, щоб його можна було легко розширювати та мати модульні компоненти.
+
+Він має:
+
+* Серйозно вражаючу продуктивність.
+* Підтримку WebSocket.
+* Фонові завдання в процесі.
+* Події запуску та завершення роботи.
+* Тестового клієнта, побудований на HTTPX.
+* CORS, GZip, статичні файли, потокові відповіді.
+* Підтримку сеансів і файлів cookie.
+* 100% покриття тестом.
+* 100% анотовану кодову базу.
+* Кілька жорстких залежностей.
+
+Starlette наразі є найшвидшим фреймворком Python із перевірених. Перевершує лише Uvicorn, який є не фреймворком, а сервером.
+
+Starlette надає всі основні функції веб-мікрофреймворку.
+
+Але він не забезпечує автоматичної перевірки даних, серіалізації чи документації.
+
+Це одна з головних речей, які **FastAPI** додає зверху, все на основі підказок типу Python (з використанням Pydantic). Це, а також система впровадження залежностей, утиліти безпеки, створення схеми OpenAPI тощо.
+
+/// note | Технічні деталі
+
+ASGI — це новий «стандарт», який розробляється членами основної команди Django. Це ще не «стандарт Python» (PEP), хоча вони в процесі цього.
+
+ Тим не менш, він уже використовується як «стандарт» кількома інструментами. Це значно покращує сумісність, оскільки ви можете переключити Uvicorn на будь-який інший сервер ASGI (наприклад, Daphne або Hypercorn), або ви можете додати інструменти, сумісні з ASGI, як-от `python-socketio`.
+
+///
+
+/// check | **FastAPI** використовує його для
+
+Керування всіма основними веб-частинами. Додавання функцій зверху.
+
+ Сам клас `FastAPI` безпосередньо успадковує клас `Starlette`.
+
+ Отже, усе, що ви можете робити зі Starlette, ви можете робити це безпосередньо за допомогою **FastAPI**, оскільки це, по суті, Starlette на стероїдах.
+
+///
+
+###
Uvicorn
+
+Uvicorn — це блискавичний сервер ASGI, побудований на uvloop і httptools.
+
+Це не веб-фреймворк, а сервер. Наприклад, він не надає інструментів для маршрутизації. Це те, що фреймворк на кшталт Starlette (або **FastAPI**) забезпечить поверх нього.
+
+Це рекомендований сервер для Starlette і **FastAPI**.
+
+/// check | **FastAPI** рекомендує це як
+
+Основний веб-сервер для запуску програм **FastAPI**.
+
+ Ви можете поєднати його з Gunicorn, щоб мати асинхронний багатопроцесний сервер.
+
+ Додаткову інформацію див. у розділі [Розгортання](deployment/index.md){.internal-link target=_blank}.
+
+///
+
+## Орієнтири та швидкість
+
+Щоб зрозуміти, порівняти та побачити різницю між Uvicorn, Starlette і FastAPI, перегляньте розділ про [Бенчмарки](benchmarks.md){.internal-link target=_blank}.
diff --git a/docs/uk/docs/fastapi-cli.md b/docs/uk/docs/fastapi-cli.md
new file mode 100644
index 000000000..6bbbbc326
--- /dev/null
+++ b/docs/uk/docs/fastapi-cli.md
@@ -0,0 +1,83 @@
+# FastAPI CLI
+
+**FastAPI CLI** це програма командного рядка, яку Ви можете використовувати, щоб обслуговувати Ваш додаток FastAPI, керувати Вашими FastApi проектами, тощо.
+
+Коли Ви встановлюєте FastApi (тобто виконуєте `pip install "fastapi[standard]"`), Ви також встановлюєте пакунок `fastapi-cli`, цей пакунок надає команду `fastapi` в терміналі.
+
+Для запуску Вашого FastAPI проекту для розробки, Ви можете скористатись командою `fastapi dev`:
+
+
+
+```console
+$ fastapi dev main.py
+INFO Using path main.py
+INFO Resolved absolute path /home/user/code/awesomeapp/main.py
+INFO Searching for package file structure from directories with __init__.py files
+INFO Importing from /home/user/code/awesomeapp
+
+ ╭─ Python module file ─╮
+ │ │
+ │ 🐍 main.py │
+ │ │
+ ╰──────────────────────╯
+
+INFO Importing module main
+INFO Found importable FastAPI app
+
+ ╭─ Importable FastAPI app ─╮
+ │ │
+ │ from main import app │
+ │ │
+ ╰──────────────────────────╯
+
+INFO Using import string main:app
+
+ ╭────────── FastAPI CLI - Development mode ───────────╮
+ │ │
+ │ Serving at: http://127.0.0.1:8000 │
+ │ │
+ │ API docs: http://127.0.0.1:8000/docs │
+ │ │
+ │ Running in development mode, for production use: │
+ │ │
+ │ fastapi run │
+ │ │
+ ╰─────────────────────────────────────────────────────╯
+
+INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp']
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [2265862] using WatchFiles
+INFO: Started server process [2265873]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+Програма командного рядка `fastapi` це **FastAPI CLI**.
+
+FastAPI CLI приймає шлях до Вашої Python програми (напр. `main.py`) і автоматично виявляє екземпляр `FastAPI` (зазвичай названий `app`), обирає коректний процес імпорту, а потім обслуговує його.
+
+Натомість, для запуску у продакшн використовуйте `fastapi run`. 🚀
+
+Всередині **FastAPI CLI** використовує
Uvicorn, високопродуктивний, production-ready, ASGI cервер. 😎
+
+## `fastapi dev`
+
+Використання `fastapi dev` ініціює режим розробки.
+
+За замовчуванням, **автоматичне перезавантаження** увімкнене, автоматично перезавантажуючи сервер кожного разу, коли Ви змінюєте Ваш код. Це ресурсо-затратно, та може бути менш стабільним, ніж коли воно вимкнене. Ви повинні використовувати його тільки під час розробки. Воно також слухає IP-адресу `127.0.0.1`, що є IP Вашого девайсу для самостійної комунікації з самим собою (`localhost`).
+
+## `fastapi run`
+
+Виконання `fastapi run` запустить FastAPI у продакшн-режимі за замовчуванням.
+
+За замовчуванням, **автоматичне перезавантаження** вимкнене. Воно також прослуховує IP-адресу `0.0.0.0`, що означає всі доступні IP адреси, тим самим даючи змогу будь-кому комунікувати з девайсом. Так Ви зазвичай будете запускати його у продакшн, наприклад у контейнері.
+
+В більшості випадків Ви можете (і маєте) мати "termination proxy", який обробляє HTTPS для Вас, це залежить від способу розгортання вашого додатку, Ваш провайдер може зробити це для Вас, або Вам потрібно налаштувати його самостійно.
+
+/// tip
+
+Ви можете дізнатись більше про це у [документації про розгортування](deployment/index.md){.internal-link target=_blank}.
+
+///
diff --git a/docs/uk/docs/features.md b/docs/uk/docs/features.md
new file mode 100644
index 000000000..7d679d8ee
--- /dev/null
+++ b/docs/uk/docs/features.md
@@ -0,0 +1,189 @@
+# Функціональні можливості
+
+## Функціональні можливості FastAPI
+
+**FastAPI** надає вам такі можливості:
+
+### Використання відкритих стандартів
+
+*
OpenAPI для створення API, включаючи оголошення
шляхів,
операцій, параметрів, тіл запитів, безпеки тощо.
+* Автоматична документація моделей даних за допомогою
JSON Schema (оскільки OpenAPI базується саме на JSON Schema).
+* Розроблено на основі цих стандартів після ретельного аналізу, а не як додатковий рівень поверх основної архітектури.
+* Це також дає змогу автоматично **генерувати код клієнта** багатьма мовами.
+
+### Автоматична генерація документації
+
+Інтерактивна документація API та вебінтерфейс для його дослідження. Оскільки фреймворк базується на OpenAPI, є кілька варіантів, два з яких включені за замовчуванням.
+
+*
Swagger UI — дозволяє інтерактивно переглядати API, викликати та тестувати його прямо у браузері.
+
+
+
+* Альтернативна документація API за допомогою
ReDoc.
+
+
+
+### Тільки сучасний Python
+
+FastAPI використовує стандартні **типи Python** (завдяки Pydantic). Вам не потрібно вивчати новий синтаксис — лише стандартний сучасний Python.
+
+Якщо вам потрібне коротке нагадування про використання типів у Python (навіть якщо ви не використовуєте FastAPI), перегляньте короткий підручник: [Вступ до типів Python](python-types.md){.internal-link target=_blank}.
+
+Ось приклад стандартного Python-коду з типами:
+
+```Python
+from datetime import date
+from pydantic import BaseModel
+
+# Оголошення змінної як str
+# з підтримкою автодоповнення у редакторі
+def main(user_id: str):
+ return user_id
+
+# Модель Pydantic
+class User(BaseModel):
+ id: int
+ name: str
+ joined: date
+```
+
+Приклад використання цієї моделі:
+
+```Python
+my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
+
+second_user_data = {
+ "id": 4,
+ "name": "Mary",
+ "joined": "2018-11-30",
+}
+
+my_second_user: User = User(**second_user_data)
+```
+
+/// info | Інформація
+
+`**second_user_data` означає:
+
+Передати ключі та значення словника `second_user_data` як аргументи у вигляді "ключ-значення", еквівалентно `User(id=4, name="Mary", joined="2018-11-30")`.
+
+///
+
+### Підтримка редакторів (IDE)
+
+Фреймворк спроєктований так, щоб бути легким і інтуїтивно зрозумілим. Усі рішення тестувалися у різних редакторах ще до початку розробки, щоб забезпечити найкращий досвід програмування.
+
+За результатами опитувань розробників Python
однією з найпопулярніших функцій є "автодоповнення".
+
+**FastAPI** повністю підтримує автодоповнення у всіх місцях, тому вам рідко доведеться повертатися до документації.
+
+Приклад автодоповнення у редакторах:
+
+* у
Visual Studio Code:
+
+
+
+* у
PyCharm:
+
+
+
+### Короткий код
+FastAPI має розумні налаштування **за замовчуванням**, але всі параметри можна налаштовувати відповідно до ваших потреб. Однак за замовчуванням все "просто працює".
+
+### Валідація
+* Підтримка валідації для більшості (або всіх?) **типів даних Python**, зокрема:
+ * JSON-об'єктів (`dict`).
+ * JSON-списків (`list`) з визначенням типів елементів.
+ * Рядків (`str`) із мінімальною та максимальною довжиною.
+ * Чисел (`int`, `float`) з обмеженнями мінімальних та максимальних значень тощо.
+
+* Валідація складніших типів, таких як:
+ * URL.
+ * Email.
+ * UUID.
+ * ...та інші.
+
+Уся валідація виконується через надійний та перевірений **Pydantic**.
+
+### Безпека та автентифікація
+
+**FastAPI** підтримує вбудовану автентифікацію та авторизацію, без прив’язки до конкретних баз даних чи моделей даних.
+
+Підтримуються всі схеми безпеки OpenAPI, включаючи:
+
+* HTTP Basic.
+* **OAuth2** (також із підтримкою **JWT-токенів**). Див. підручник: [OAuth2 із JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
+* Ключі API в:
+ * Заголовках.
+ * Параметрах запиту.
+ * Cookies тощо.
+
+А також усі можливості безпеки від Starlette (зокрема **сесійні cookies**).
+
+Усі вони створені як багаторазові інструменти та компоненти, які легко інтегруються з вашими системами, сховищами даних, реляційними та NoSQL базами даних тощо.
+
+### Впровадження залежностей
+
+**FastAPI** містить надзвичайно просту у використанні, але потужну систему впровадження залежностей.
+
+* Залежності можуть мати власні залежності, утворюючи ієрархію або **"граф залежностей"**.
+* Усі залежності автоматично керуються фреймворком.
+* Усі залежності можуть отримувати дані з запитів і розширювати **обмеження операції за шляхом** та автоматичну документацію.
+* **Автоматична валідація** навіть для параметрів *операцій шляху*, визначених у залежностях.
+* Підтримка складних систем автентифікації користувачів, **з'єднань із базами даних** тощо.
+* **Жодних обмежень** щодо використання баз даних, фронтендів тощо, але водночас проста інтеграція з усіма ними.
+
+### Немає обмежень на "плагіни"
+
+Або іншими словами, вони не потрібні – просто імпортуйте та використовуйте необхідний код.
+
+Будь-яка інтеграція спроєктована настільки просто (з використанням залежностей), що ви можете створити "плагін" для свого застосунку всього у 2 рядках коду, використовуючи ту саму структуру та синтаксис, що й для ваших *операцій шляху*.
+
+### Протестовано
+
+* 100%
покриття тестами.
+* 100%
анотована типами кодова база.
+* Використовується у робочих середовищах.
+
+## Можливості Starlette
+
+**FastAPI** повністю сумісний із (та побудований на основі)
Starlette. Тому будь-який додатковий код Starlette, який ви маєте, також працюватиме.
+
+**FastAPI** фактично є підкласом **Starlette**. Тому, якщо ви вже знайомі зі Starlette або використовуєте його, більшість функціональності працюватиме так само.
+
+З **FastAPI** ви отримуєте всі можливості **Starlette** (адже FastAPI — це, по суті, Starlette на стероїдах):
+
+* Разюча продуктивність. Це
один із найшвидших фреймворків на Python, на рівні з **NodeJS** і **Go**.
+* Підтримка **WebSocket**.
+* Фонові задачі у процесі.
+* Події запуску та завершення роботи.
+* Клієнт для тестування, побудований на HTTPX.
+* Підтримка **CORS**, **GZip**, статичних файлів, потокових відповідей.
+* Підтримка **сесій** і **cookie**.
+* 100% покриття тестами.
+* 100% анотована типами кодова база.
+
+## Можливості Pydantic
+
+**FastAPI** повністю сумісний із (та побудований на основі)
Pydantic. Тому будь-який додатковий код Pydantic, який ви маєте, також працюватиме.
+
+Включаючи зовнішні бібліотеки, побудовані також на Pydantic, такі як
ORM,
ODM для баз даних.
+
+Це також означає, що в багатьох випадках ви можете передати той самий об'єкт, який отримуєте з запиту, **безпосередньо в базу даних**, оскільки все автоматично перевіряється.
+
+Те ж саме відбувається й у зворотному напрямку — у багатьох випадках ви можете просто передати об'єкт, який отримуєте з бази даних, **безпосередньо клієнту**.
+
+З **FastAPI** ви отримуєте всі можливості **Pydantic** (адже FastAPI базується на Pydantic для обробки всіх даних):
+
+* **Ніякої плутанини** :
+ * Не потрібно вчити нову мову для визначення схем.
+ * Якщо ви знаєте типи Python, ви знаєте, як використовувати Pydantic.
+* Легко працює з вашим **
IDE/
лінтером/мозком**:
+ * Оскільки структури даних Pydantic є просто екземплярами класів, які ви визначаєте; автодоповнення, лінтинг, mypy і ваша інтуїція повинні добре працювати з вашими перевіреними даними.
+* Валідація **складних структур**:
+ * Використання ієрархічних моделей Pydantic. Python `typing`, `List` і `Dict` тощо.
+ * Валідатори дозволяють чітко і просто визначати, перевіряти й документувати складні схеми даних у вигляді JSON-схеми.
+ * Ви можете мати глибоко **вкладені JSON об'єкти** та перевірити та анотувати їх всі.
+* **Розширюваність**:
+ * Pydantic дозволяє визначати користувацькі типи даних або розширювати валідацію методами в моделі декоратором `validator`.
+* 100% покриття тестами.
diff --git a/docs/uk/docs/index.md b/docs/uk/docs/index.md
index 95fb7ae21..b573ee259 100644
--- a/docs/uk/docs/index.md
+++ b/docs/uk/docs/index.md
@@ -1,50 +1,49 @@
-
-{!../../../docs/missing-translation.md!}
-
-
- FastAPI framework, high performance, easy to learn, fast to code, ready for production
+ Готовий до продакшину, високопродуктивний, простий у вивченні та швидкий для написання коду фреймворк
-
-
+
+
-
-
+
+
+
+
+
---
-**Documentation**:
https://fastapi.tiangolo.com
+**Документація**:
https://fastapi.tiangolo.com
-**Source Code**:
https://github.com/tiangolo/fastapi
+**Програмний код**:
https://github.com/fastapi/fastapi
---
-FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
+FastAPI - це сучасний, швидкий (високопродуктивний), вебфреймворк для створення API за допомогою Python,в основі якого лежить стандартна анотація типів Python.
-The key features are:
+Ключові особливості:
-* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
+* **Швидкий**: Дуже висока продуктивність, на рівні з **NodeJS** та **Go** (завдяки Starlette та Pydantic). [Один із найшвидших фреймворків](#performance).
-* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
-* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
-* **Intuitive**: Great editor support.
Completion everywhere. Less time debugging.
-* **Easy**: Designed to be easy to use and learn. Less time reading docs.
-* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
-* **Robust**: Get production-ready code. With automatic interactive documentation.
-* **Standards-based**: Based on (and fully compatible with) the open standards for APIs:
OpenAPI (previously known as Swagger) and
JSON Schema.
+* **Швидке написання коду**: Пришвидшує розробку функціоналу приблизно на 200%-300%. *
+* **Менше помилок**: Зменшить кількість помилок спричинених людиною (розробником) на 40%. *
+* **Інтуїтивний**: Чудова підтримка редакторами коду.
Доповнення всюди. Зменште час на налагодження.
+* **Простий**: Спроектований, для легкого використання та навчання. Знадобиться менше часу на читання документації.
+* **Короткий**: Зведе до мінімуму дублювання коду. Кожен оголошений параметр може виконувати кілька функцій.
+* **Надійний**: Ви матимете стабільний код готовий до продакшину з автоматичною інтерактивною документацією.
+* **Стандартизований**: Оснований та повністю сумісний з відкритими стандартами для API:
OpenAPI (попередньо відомий як Swagger) та
JSON Schema.
-
* estimation based on tests on an internal development team, building production applications.
+
* оцінка на основі тестів внутрішньої команди розробників, створення продуктових застосунків.
-## Sponsors
+## Спонсори
@@ -61,11 +60,11 @@ The key features are:
Other sponsors
-## Opinions
+## Враження
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
-
Kabir Khan -
Microsoft (ref)
+
Kabir Khan -
Microsoft (ref)
---
@@ -89,7 +88,7 @@ The key features are:
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
-
+
---
@@ -101,24 +100,22 @@ The key features are:
---
-## **Typer**, the FastAPI of CLIs
+## **Typer**, FastAPI CLI

-If you are building a
CLI app to be used in the terminal instead of a web API, check out
**Typer**.
-
-**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
+Створюючи
CLI застосунок для використання в терміналі, замість веб-API зверніть увагу на
**Typer**.
-## Requirements
+**Typer** є молодшим братом FastAPI. І це **FastAPI для CLI**. ⌨️ 🚀
-Python 3.6+
+## Вимоги
-FastAPI stands on the shoulders of giants:
+FastAPI стоїть на плечах гігантів:
-*
Starlette for the web parts.
-*
Pydantic for the data parts.
+*
Starlette для web частини.
+*
Pydantic для частини даних.
-## Installation
+## Вставновлення
@@ -130,7 +127,7 @@ $ pip install fastapi
-You will also need an ASGI server, for production such as
Uvicorn or
Hypercorn.
+Вам також знадобиться сервер ASGI для продакшину, наприклад
Uvicorn або
Hypercorn.
@@ -142,14 +139,14 @@ $ pip install uvicorn[standard]
-## Example
+## Приклад
-### Create it
+### Створіть
-* Create a file `main.py` with:
+* Створіть файл `main.py` з:
```Python
-from typing import Optional
+from typing import Union
from fastapi import FastAPI
@@ -162,17 +159,17 @@ def read_root():
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: Optional[str] = None):
+def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
-Or use async def
...
+Або використайте async def
...
-If your code uses `async` / `await`, use `async def`:
+Якщо ваш код використовує `async` / `await`, скористайтеся `async def`:
```Python hl_lines="9 14"
-from typing import Optional
+from typing import Union
from fastapi import FastAPI
@@ -185,19 +182,19 @@ async def read_root():
@app.get("/items/{item_id}")
-async def read_item(item_id: int, q: Optional[str] = None):
+async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
-**Note**:
+**Примітка**:
-If you don't know, check the _"In a hurry?"_ section about `async` and `await` in the docs.
+Стикнувшись з проблемами, не зайвим буде ознайомитися з розділом _"In a hurry?"_ про `async` та `await` у документації.
-### Run it
+### Запустіть
-Run the server with:
+Запустіть server з:
@@ -214,57 +211,57 @@ INFO: Application startup complete.
-About the command uvicorn main:app --reload
...
+Про команди uvicorn main:app --reload
...
-The command `uvicorn main:app` refers to:
+Команда `uvicorn main:app` посилається на:
-* `main`: the file `main.py` (the Python "module").
-* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
-* `--reload`: make the server restart after code changes. Only do this for development.
+* `main`: файл `main.py` ("Модуль" Python).
+* `app`: об’єкт створений усередині `main.py` рядком `app = FastAPI()`.
+* `--reload`: перезапускає сервер після зміни коду. Використовуйте виключно для розробки.
-### Check it
+### Перевірте
-Open your browser at
http://127.0.0.1:8000/items/5?q=somequery.
+Відкрийте браузер та введіть адресу
http://127.0.0.1:8000/items/5?q=somequery.
-You will see the JSON response as:
+Ви побачите у відповідь подібний JSON:
```JSON
{"item_id": 5, "q": "somequery"}
```
-You already created an API that:
+Ви вже створили API, який:
-* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`.
-* Both _paths_ take `GET`
operations (also known as HTTP _methods_).
-* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
-* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
+* Отримує HTTP запити за _шляхами_ `/` та `/items/{item_id}`.
+* Обидва _шляхи_ приймають `GET`
операції (також відомі як HTTP _методи_).
+* _Шлях_ `/items/{item_id}` містить _параметр шляху_ `item_id` який має бути типу `int`.
+* _Шлях_ `/items/{item_id}` містить необовʼязковий `str` _параметр запиту_ `q`.
-### Interactive API docs
+### Інтерактивні документації API
-Now go to
http://127.0.0.1:8000/docs.
+Перейдемо сюди
http://127.0.0.1:8000/docs.
-You will see the automatic interactive API documentation (provided by
Swagger UI):
+Ви побачите автоматичну інтерактивну API документацію (створену завдяки
Swagger UI):

-### Alternative API docs
+### Альтернативні документації API
-And now, go to
http://127.0.0.1:8000/redoc.
+Тепер перейдемо сюди
http://127.0.0.1:8000/redoc.
-You will see the alternative automatic documentation (provided by
ReDoc):
+Ви побачите альтернативну автоматичну документацію (створену завдяки
ReDoc):

-## Example upgrade
+## Приклад оновлення
-Now modify the file `main.py` to receive a body from a `PUT` request.
+Тепер модифікуйте файл `main.py`, щоб отримати вміст запиту `PUT`.
-Declare the body using standard Python types, thanks to Pydantic.
+Оголошуйте вміст запиту за допомогою стандартних типів Python завдяки Pydantic.
```Python hl_lines="4 9-12 25-27"
-from typing import Optional
+from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
@@ -275,7 +272,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
- is_offer: Optional[bool] = None
+ is_offer: Union[bool, None] = None
@app.get("/")
@@ -284,7 +281,7 @@ def read_root():
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: Optional[str] = None):
+def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
@@ -293,175 +290,174 @@ def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
-The server should reload automatically (because you added `--reload` to the `uvicorn` command above).
+Сервер повинен автоматично перезавантажуватися (тому що Ви додали `--reload` до `uvicorn` команди вище).
-### Interactive API docs upgrade
+### Оновлення інтерактивної API документації
-Now go to
http://127.0.0.1:8000/docs.
+Тепер перейдемо сюди
http://127.0.0.1:8000/docs.
-* The interactive API documentation will be automatically updated, including the new body:
+* Інтерактивна документація API буде автоматично оновлена, включаючи новий вміст:

-* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:
+* Натисніть кнопку "Try it out", це дозволить вам заповнити параметри та безпосередньо взаємодіяти з API:

-* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen:
+* Потім натисніть кнопку "Execute", інтерфейс користувача зв'яжеться з вашим API, надішле параметри, у відповідь отримає результати та покаже їх на екрані:

-### Alternative API docs upgrade
+### Оновлення альтернативної API документації
-And now, go to
http://127.0.0.1:8000/redoc.
+Зараз перейдемо
http://127.0.0.1:8000/redoc.
-* The alternative documentation will also reflect the new query parameter and body:
+* Альтернативна документація також показуватиме новий параметр і вміст запиту:

-### Recap
+### Підсумки
-In summary, you declare **once** the types of parameters, body, etc. as function parameters.
+Таким чином, Ви **один раз** оголошуєте типи параметрів, тіла тощо, як параметри функції.
-You do that with standard modern Python types.
+Ви робите це за допомогою стандартних сучасних типів Python.
-You don't have to learn a new syntax, the methods or classes of a specific library, etc.
+Вам не потрібно вивчати новий синтаксис, методи чи класи конкретної бібліотеки тощо.
-Just standard **Python 3.6+**.
+Використовуючи стандартний **Python**.
-For example, for an `int`:
+Наприклад, для `int`:
```Python
item_id: int
```
-or for a more complex `Item` model:
+або для більш складної моделі `Item`:
```Python
item: Item
```
-...and with that single declaration you get:
+...і з цим єдиним оголошенням Ви отримуєте:
-* Editor support, including:
- * Completion.
- * Type checks.
-* Validation of data:
- * Automatic and clear errors when the data is invalid.
- * Validation even for deeply nested JSON objects.
-*
Conversion of input data: coming from the network to Python data and types. Reading from:
+* Підтримку редактора, включаючи:
+ * Варіанти заповнення.
+ * Перевірку типів.
+* Перевірку даних:
+ * Автоматичні та зрозумілі помилки, у разі некоректних даних.
+ * Перевірка навіть для JSON з високим рівнем вкладеності.
+*
Перетворення вхідних даних: з мережі до даних і типів Python. Читання з:
* JSON.
- * Path parameters.
- * Query parameters.
+ * Параметрів шляху.
+ * Параметрів запиту.
* Cookies.
* Headers.
* Forms.
- * Files.
-*
Conversion of output data: converting from Python data and types to network data (as JSON):
- * Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
- * `datetime` objects.
- * `UUID` objects.
- * Database models.
- * ...and many more.
-* Automatic interactive API documentation, including 2 alternative user interfaces:
+ * Файлів.
+*
Перетворення вихідних даних: з типів і даних Python до мережевих даних (як JSON):
+ * Конвертація Python типів (`str`, `int`, `float`, `bool`, `list`, тощо).
+ * `datetime` об'єкти.
+ * `UUID` об'єкти.
+ * Моделі бази даних.
+ * ...та багато іншого.
+* Автоматичну інтерактивну документацію API, включаючи 2 альтернативні інтерфейси користувача:
* Swagger UI.
* ReDoc.
---
-Coming back to the previous code example, **FastAPI** will:
-
-* Validate that there is an `item_id` in the path for `GET` and `PUT` requests.
-* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests.
- * If it is not, the client will see a useful, clear error.
-* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests.
- * As the `q` parameter is declared with `= None`, it is optional.
- * Without the `None` it would be required (as is the body in the case with `PUT`).
-* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
- * Check that it has a required attribute `name` that should be a `str`.
- * Check that it has a required attribute `price` that has to be a `float`.
- * Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
- * All this would also work for deeply nested JSON objects.
-* Convert from and to JSON automatically.
-* Document everything with OpenAPI, that can be used by:
- * Interactive documentation systems.
- * Automatic client code generation systems, for many languages.
-* Provide 2 interactive documentation web interfaces directly.
+Повертаючись до попереднього прикладу коду, **FastAPI**:
+
+* Підтвердить наявність `item_id` у шляху для запитів `GET` та `PUT`.
+* Підтвердить, що `item_id` має тип `int` для запитів `GET` and `PUT`.
+ * Якщо це не так, клієнт побачить корисну, зрозумілу помилку.
+* Перевірить, чи є необов'язковий параметр запиту з назвою `q` (а саме `http://127.0.0.1:8000/items/foo?q=somequery`) для запитів `GET`.
+ * Оскільки параметр `q` оголошено як `= None`, він необов'язковий.
+ * За відсутності `None` він був би обов'язковим (як і вміст у випадку з `PUT`).
+* Для запитів `PUT` із `/items/{item_id}`, читає вміст як JSON:
+ * Перевірить, чи має обов'язковий атрибут `name` тип `str`.
+ * Перевірить, чи має обов'язковий атрибут `price` тип `float`.
+ * Перевірить, чи існує необов'язковий атрибут `is_offer` та чи має він тип `bool`.
+ * Усе це також працюватиме для глибоко вкладених об'єктів JSON.
+* Автоматично конвертує із та в JSON.
+* Документує все за допомогою OpenAPI, який може бути використано в:
+ * Інтерактивних системах документації.
+ * Системах автоматичної генерації клієнтського коду для багатьох мов.
+* Надає безпосередньо 2 вебінтерфейси інтерактивної документації.
---
-We just scratched the surface, but you already get the idea of how it all works.
+Ми лише трішки доторкнулися до коду, але Ви вже маєте уявлення про те, як все працює.
-Try changing the line with:
+Спробуйте змінити рядок:
```Python
return {"item_name": item.name, "item_id": item_id}
```
-...from:
+...із:
```Python
... "item_name": item.name ...
```
-...to:
+...на:
```Python
... "item_price": item.price ...
```
-...and see how your editor will auto-complete the attributes and know their types:
+...і побачите, як ваш редактор автоматично заповнюватиме атрибути та знатиме їхні типи:

-For a more complete example including more features, see the
Tutorial - User Guide.
+Для більш повного ознайомлення з додатковими функціями, перегляньте
Туторіал - Посібник Користувача.
-**Spoiler alert**: the tutorial - user guide includes:
+**Spoiler alert**: туторіал - посібник користувача містить:
-* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
-* How to set **validation constraints** as `maximum_length` or `regex`.
-* A very powerful and easy to use **
Dependency Injection** system.
-* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
-* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
-* Many extra features (thanks to Starlette) as:
+* Оголошення **параметрів** з інших місць як: **headers**, **cookies**, **form fields** та **files**.
+* Як встановити **перевірку обмежень** як `maximum_length` або `regex`.
+* Дуже потужна і проста у використанні система **
Ін'єкція Залежностей**.
+* Безпека та автентифікація, включаючи підтримку **OAuth2** з **JWT tokens** та **HTTP Basic** автентифікацію.
+* Досконаліші (але однаково прості) техніки для оголошення **глибоко вкладених моделей JSON** (завдяки Pydantic).
+* Багато додаткових функцій (завдяки Starlette) як-от:
* **WebSockets**
- * **GraphQL**
- * extremely easy tests based on `requests` and `pytest`
+ * надзвичайно прості тести на основі HTTPX та `pytest`
* **CORS**
* **Cookie Sessions**
- * ...and more.
+ * ...та більше.
+
+## Продуктивність
-## Performance
+Незалежні тести TechEmpower показують що застосунки **FastAPI**, які працюють під керуванням Uvicorn
є одними з найшвидших серед доступних фреймворків в Python, поступаючись лише Starlette та Uvicorn (які внутрішньо використовуються в FastAPI). (*)
-Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as
one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
+Щоб дізнатися більше про це, перегляньте розділ
Benchmarks.
-To understand more about it, see the section
Benchmarks.
+## Необов'язкові залежності
-## Optional Dependencies
+Pydantic використовує:
-Used by Pydantic:
+*
email-validator
- для валідації електронної пошти.
+*
pydantic-settings
- для управління налаштуваннями.
+*
pydantic-extra-types
- для додаткових типів, що можуть бути використані з Pydantic.
-*
ujson
- for faster JSON
"parsing".
-*
email_validator
- for email validation.
-Used by Starlette:
+Starlette використовує:
-*
requests
- Required if you want to use the `TestClient`.
-*
aiofiles
- Required if you want to use `FileResponse` or `StaticFiles`.
-*
jinja2
- Required if you want to use the default template configuration.
-*
python-multipart
- Required if you want to support form
"parsing", with `request.form()`.
-*
itsdangerous
- Required for `SessionMiddleware` support.
-*
pyyaml
- Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
-*
graphene
- Required for `GraphQLApp` support.
-*
ujson
- Required if you want to use `UJSONResponse`.
+*
httpx
- Необхідно, якщо Ви хочете використовувати `TestClient`.
+*
jinja2
- Необхідно, якщо Ви хочете використовувати шаблони як конфігурацію за замовчуванням.
+*
python-multipart
- Необхідно, якщо Ви хочете підтримувати
"розбір" форми за допомогою `request.form()`.
+*
itsdangerous
- Необхідно для підтримки `SessionMiddleware`.
+*
pyyaml
- Необхідно для підтримки Starlette `SchemaGenerator` (ймовірно, вам це не потрібно з FastAPI).
-Used by FastAPI / Starlette:
+FastAPI / Starlette використовують:
-*
uvicorn
- for the server that loads and serves your application.
-*
orjson
- Required if you want to use `ORJSONResponse`.
+*
uvicorn
- для сервера, який завантажує та обслуговує вашу програму.
+*
orjson
- Необхідно, якщо Ви хочете використовувати `ORJSONResponse`.
+*
ujson
- Необхідно, якщо Ви хочете використовувати `UJSONResponse`.
-You can install all of these with `pip install fastapi[all]`.
+Ви можете встановити все це за допомогою `pip install fastapi[all]`.
-## License
+## Ліцензія
-This project is licensed under the terms of the MIT license.
+Цей проєкт ліцензовано згідно з умовами ліцензії MIT.
diff --git a/docs/uk/docs/learn/index.md b/docs/uk/docs/learn/index.md
new file mode 100644
index 000000000..7f9f21e57
--- /dev/null
+++ b/docs/uk/docs/learn/index.md
@@ -0,0 +1,5 @@
+# Навчання
+
+У цьому розділі надані вступні та навчальні матеріали для вивчення FastAPI.
+
+Це можна розглядати як **книгу**, **курс**, або **офіційний** та рекомендований спосіб освоїти FastAPI. 😎
diff --git a/docs/uk/docs/python-types.md b/docs/uk/docs/python-types.md
new file mode 100644
index 000000000..676bafb15
--- /dev/null
+++ b/docs/uk/docs/python-types.md
@@ -0,0 +1,489 @@
+# Вступ до типів Python
+
+Python підтримує додаткові "підказки типу" ("type hints") (також звані "анотаціями типу" ("type annotations")).
+
+Ці **"type hints"** є спеціальним синтаксисом, що дозволяє оголошувати
тип змінної.
+
+За допомогою оголошення типів для ваших змінних, редактори та інструменти можуть надати вам кращу підтримку.
+
+Це просто **швидкий посібник / нагадування** про анотації типів у Python. Він покриває лише мінімум, необхідний щоб використовувати їх з **FastAPI**... що насправді дуже мало.
+
+**FastAPI** повністю базується на цих анотаціях типів, вони дають йому багато переваг.
+
+Але навіть якщо ви ніколи не використаєте **FastAPI**, вам буде корисно дізнатись трохи про них.
+
+/// note
+
+Якщо ви експерт у Python і ви вже знаєте усе про анотації типів - перейдіть до наступного розділу.
+
+///
+
+## Мотивація
+
+Давайте почнемо з простого прикладу:
+
+{* ../../docs_src/python_types/tutorial001.py *}
+
+
+Виклик цієї програми виводить:
+
+```
+John Doe
+```
+
+Функція виконує наступне:
+
+* Бере `first_name` та `last_name`.
+* Конвертує кожну літеру кожного слова у верхній регістр за допомогою `title()`.
+*
Конкатенує їх разом із пробілом по середині.
+
+{* ../../docs_src/python_types/tutorial001.py hl[2] *}
+
+
+### Редагуйте це
+
+Це дуже проста програма.
+
+Але тепер уявіть, що ви писали це з нуля.
+
+У певний момент ви розпочали б визначення функції, у вас були б готові параметри...
+
+Але тоді вам потрібно викликати "той метод, який переводить першу літеру у верхній регістр".
+
+Це буде `upper`? Чи `uppercase`? `first_uppercase`? `capitalize`?
+
+Тоді ви спробуєте давнього друга програміста - автозаповнення редактора коду.
+
+Ви надрукуєте перший параметр функції, `first_name`, тоді крапку (`.`), а тоді натиснете `Ctrl+Space`, щоб запустити автозаповнення.
+
+Але, на жаль, ви не отримаєте нічого корисного:
+
+

+
+### Додайте типи
+
+Давайте змінимо один рядок з попередньої версії.
+
+Ми змінимо саме цей фрагмент, параметри функції, з:
+
+```Python
+ first_name, last_name
+```
+
+на:
+
+```Python
+ first_name: str, last_name: str
+```
+
+Ось і все.
+
+Це "type hints":
+
+{* ../../docs_src/python_types/tutorial002.py hl[1] *}
+
+
+Це не те саме, що оголошення значень за замовчуванням, як це було б з:
+
+```Python
+ first_name="john", last_name="doe"
+```
+
+Це зовсім інше.
+
+Ми використовуємо двокрапку (`:`), не дорівнює (`=`).
+
+І додавання анотації типу зазвичай не змінює того, що сталось би без них.
+
+Але тепер, уявіть що ви посеред процесу створення функції, але з анотаціями типів.
+
+В цей же момент, ви спробуєте викликати автозаповнення з допомогою `Ctrl+Space` і побачите:
+
+

+
+Разом з цим, ви можете прокручувати, переглядати опції, допоки ви не знайдете одну, що звучить схоже:
+
+

+
+## Більше мотивації
+
+Перевірте цю функцію, вона вже має анотацію типу:
+
+{* ../../docs_src/python_types/tutorial003.py hl[1] *}
+
+
+Оскільки редактор знає типи змінних, ви не тільки отримаєте автозаповнення, ви також отримаєте перевірку помилок:
+
+

+
+Тепер ви знаєте, щоб виправити це, вам потрібно перетворити `age` у строку з допомогою `str(age)`:
+
+{* ../../docs_src/python_types/tutorial004.py hl[2] *}
+
+
+## Оголошення типів
+
+Щойно ви побачили основне місце для оголошення анотацій типу. Як параметри функції.
+
+Це також основне місце, де ви б їх використовували у **FastAPI**.
+
+### Прості типи
+
+Ви можете оголошувати усі стандартні типи у Python, не тільки `str`.
+
+Ви можете використовувати, наприклад:
+
+* `int`
+* `float`
+* `bool`
+* `bytes`
+
+{* ../../docs_src/python_types/tutorial005.py hl[1] *}
+
+
+### Generic-типи з параметрами типів
+
+Існують деякі структури даних, які можуть містити інші значення, наприклад `dict`, `list`, `set` та `tuple`. І внутрішні значення також можуть мати свій тип.
+
+Ці типи, які мають внутрішні типи, називаються "**generic**" типами. І оголосити їх можна навіть із внутрішніми типами.
+
+Щоб оголосити ці типи та внутрішні типи, ви можете використовувати стандартний модуль Python `typing`. Він існує спеціально для підтримки анотацій типів.
+
+#### Новіші версії Python
+
+Синтаксис із використанням `typing` **сумісний** з усіма версіями, від Python 3.6 до останніх, включаючи Python 3.9, Python 3.10 тощо.
+
+У міру розвитку Python **новіші версії** мають покращену підтримку анотацій типів і в багатьох випадках вам навіть не потрібно буде імпортувати та використовувати модуль `typing` для оголошення анотацій типу.
+
+Якщо ви можете вибрати новішу версію Python для свого проекту, ви зможете скористатися цією додатковою простотою. Дивіться кілька прикладів нижче.
+
+#### List (список)
+
+Наприклад, давайте визначимо змінну, яка буде `list` із `str`.
+
+//// tab | Python 3.8 і вище
+
+З модуля `typing`, імпортуємо `List` (з великої літери `L`):
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial006.py!}
+```
+
+Оголосимо змінну з тим самим синтаксисом двокрапки (`:`).
+
+Як тип вкажемо `List`, який ви імпортували з `typing`.
+
+Оскільки список є типом, який містить деякі внутрішні типи, ви поміщаєте їх у квадратні дужки:
+
+```Python hl_lines="4"
+{!> ../../docs_src/python_types/tutorial006.py!}
+```
+
+////
+
+//// tab | Python 3.9 і вище
+
+Оголосимо змінну з тим самим синтаксисом двокрапки (`:`).
+
+Як тип вкажемо `list`.
+
+Оскільки список є типом, який містить деякі внутрішні типи, ви поміщаєте їх у квадратні дужки:
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial006_py39.py!}
+```
+
+////
+
+/// info
+
+Ці внутрішні типи в квадратних дужках називаються "параметрами типу".
+
+У цьому випадку, `str` це параметр типу переданий у `List` (або `list` у Python 3.9 і вище).
+
+///
+
+Це означає: "змінна `items` це `list`, і кожен з елементів у цьому списку - `str`".
+
+/// tip
+
+Якщо ви використовуєте Python 3.9 і вище, вам не потрібно імпортувати `List` з `typing`, ви можете використовувати натомість тип `list`.
+
+///
+
+Зробивши це, ваш редактор може надати підтримку навіть під час обробки елементів зі списку:
+
+

+
+Без типів цього майже неможливо досягти.
+
+Зверніть увагу, що змінна `item` є одним із елементів у списку `items`.
+
+І все ж редактор знає, що це `str`, і надає підтримку для цього.
+
+#### Tuple and Set (кортеж та набір)
+
+Ви повинні зробити те ж саме, щоб оголосити `tuple` і `set`:
+
+//// tab | Python 3.8 і вище
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial007.py!}
+```
+
+////
+
+//// tab | Python 3.9 і вище
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial007_py39.py!}
+```
+
+////
+
+Це означає:
+
+* Змінна `items_t` це `tuple` з 3 елементами, `int`, ще `int`, та `str`.
+* Змінна `items_s` це `set`, і кожен його елемент типу `bytes`.
+
+#### Dict (словник)
+
+Щоб оголосити `dict`, вам потрібно передати 2 параметри типу, розділені комами.
+
+Перший параметр типу для ключа у `dict`.
+
+Другий параметр типу для значення у `dict`:
+
+//// tab | Python 3.8 і вище
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial008.py!}
+```
+
+////
+
+//// tab | Python 3.9 і вище
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial008_py39.py!}
+```
+
+////
+
+Це означає:
+
+* Змінна `prices` це `dict`:
+ * Ключі цього `dict` типу `str` (наприклад, назва кожного елементу).
+ * Значення цього `dict` типу `float` (наприклад, ціна кожного елементу).
+
+#### Union (об'єднання)
+
+Ви можете оголосити, що змінна може бути будь-яким із **кількох типів**, наприклад, `int` або `str`.
+
+У Python 3.6 і вище (включаючи Python 3.10) ви можете використовувати тип `Union` з `typing` і вставляти в квадратні дужки можливі типи, які можна прийняти.
+
+У Python 3.10 також є **альтернативний синтаксис**, у якому ви можете розділити можливі типи за допомогою
вертикальної смуги (`|`).
+
+//// tab | Python 3.8 і вище
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial008b.py!}
+```
+
+////
+
+//// tab | Python 3.10 і вище
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial008b_py310.py!}
+```
+
+////
+
+В обох випадках це означає, що `item` може бути `int` або `str`.
+
+#### Possibly `None` (Optional)
+
+Ви можете оголосити, що значення може мати тип, наприклад `str`, але також може бути `None`.
+
+У Python 3.6 і вище (включаючи Python 3.10) ви можете оголосити його, імпортувавши та використовуючи `Optional` з модуля `typing`.
+
+```Python hl_lines="1 4"
+{!../../docs_src/python_types/tutorial009.py!}
+```
+
+Використання `Optional[str]` замість просто `str` дозволить редактору допомогти вам виявити помилки, коли ви могли б вважати, що значенням завжди є `str`, хоча насправді воно також може бути `None`.
+
+`Optional[Something]` насправді є скороченням для `Union[Something, None]`, вони еквівалентні.
+
+Це також означає, що в Python 3.10 ви можете використовувати `Something | None`:
+
+//// tab | Python 3.8 і вище
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial009.py!}
+```
+
+////
+
+//// tab | Python 3.8 і вище - альтернатива
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial009b.py!}
+```
+
+////
+
+//// tab | Python 3.10 і вище
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial009_py310.py!}
+```
+
+////
+
+#### Generic типи
+
+Ці типи, які приймають параметри типу у квадратних дужках, називаються **Generic types** or **Generics**, наприклад:
+
+//// tab | Python 3.8 і вище
+
+* `List`
+* `Tuple`
+* `Set`
+* `Dict`
+* `Union`
+* `Optional`
+* ...та інші.
+
+////
+
+//// tab | Python 3.9 і вище
+
+Ви можете використовувати ті самі вбудовані типи, як generic (з квадратними дужками та типами всередині):
+
+* `list`
+* `tuple`
+* `set`
+* `dict`
+
+І те саме, що й у Python 3.8, із модуля `typing`:
+
+* `Union`
+* `Optional`
+* ...та інші.
+
+////
+
+//// tab | Python 3.10 і вище
+
+Ви можете використовувати ті самі вбудовані типи, як generic (з квадратними дужками та типами всередині):
+
+* `list`
+* `tuple`
+* `set`
+* `dict`
+
+І те саме, що й у Python 3.8, із модуля `typing`:
+
+* `Union`
+* `Optional` (так само як у Python 3.8)
+* ...та інші.
+
+У Python 3.10, як альтернатива використанню `Union` та `Optional`, ви можете використовувати
вертикальну смугу (`|`) щоб оголосити об'єднання типів.
+
+////
+
+### Класи як типи
+
+Ви також можете оголосити клас як тип змінної.
+
+Скажімо, у вас є клас `Person` з імʼям:
+
+{* ../../docs_src/python_types/tutorial010.py hl[1:3] *}
+
+
+Потім ви можете оголосити змінну типу `Person`:
+
+{* ../../docs_src/python_types/tutorial010.py hl[6] *}
+
+
+І знову ж таки, ви отримуєте всю підтримку редактора:
+
+

+
+## Pydantic моделі
+
+
Pydantic це бібліотека Python для валідації даних.
+
+Ви оголошуєте «форму» даних як класи з атрибутами.
+
+І кожен атрибут має тип.
+
+Потім ви створюєте екземпляр цього класу з деякими значеннями, і він перевірить ці значення, перетворить їх у відповідний тип (якщо є потреба) і надасть вам об’єкт з усіма даними.
+
+І ви отримуєте всю підтримку редактора з цим отриманим об’єктом.
+
+Приклад з документації Pydantic:
+
+//// tab | Python 3.8 і вище
+
+```Python
+{!> ../../docs_src/python_types/tutorial011.py!}
+```
+
+////
+
+//// tab | Python 3.9 і вище
+
+```Python
+{!> ../../docs_src/python_types/tutorial011_py39.py!}
+```
+
+////
+
+//// tab | Python 3.10 і вище
+
+```Python
+{!> ../../docs_src/python_types/tutorial011_py310.py!}
+```
+
+////
+
+/// info
+
+Щоб дізнатись більше про
Pydantic, перегляньте його документацію.
+
+///
+
+**FastAPI** повністю базується на Pydantic.
+
+Ви побачите набагато більше цього всього на практиці в [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}.
+
+## Анотації типів у **FastAPI**
+
+**FastAPI** використовує ці підказки для виконання кількох речей.
+
+З **FastAPI** ви оголошуєте параметри з підказками типу, і отримуєте:
+
+* **Підтримку редактора**.
+* **Перевірку типів**.
+
+...і **FastAPI** використовує ті самі оголошення для:
+
+* **Визначення вимог**: з параметрів шляху запиту, параметрів запиту, заголовків, тіл, залежностей тощо.
+* **Перетворення даних**: із запиту в необхідний тип.
+* **Перевірка даних**: що надходять від кожного запиту:
+ * Генерування **автоматичних помилок**, що повертаються клієнту, коли дані недійсні.
+* **Документування** API за допомогою OpenAPI:
+ * який потім використовується для автоматичної інтерактивної документації користувальницьких інтерфейсів.
+
+Все це може здатися абстрактним. Не хвилюйтеся. Ви побачите все це в дії в [Туторіал - Посібник користувача](tutorial/index.md){.internal-link target=_blank}.
+
+Важливо те, що за допомогою стандартних типів Python в одному місці (замість того, щоб додавати більше класів, декораторів тощо), **FastAPI** зробить багато роботи за вас.
+
+/// info
+
+Якщо ви вже пройшли весь навчальний посібник і повернулися, щоб дізнатися більше про типи, ось хороший ресурс
"шпаргалка" від `mypy`.
+
+///
diff --git a/docs/uk/docs/tutorial/background-tasks.md b/docs/uk/docs/tutorial/background-tasks.md
new file mode 100644
index 000000000..912ba8c2a
--- /dev/null
+++ b/docs/uk/docs/tutorial/background-tasks.md
@@ -0,0 +1,85 @@
+# Фонові задачі
+
+Ви можете створювати фонові задачі, які будуть виконуватися *після* повернення відповіді.
+
+Це корисно для операцій, які потрібно виконати після обробки запиту, але клієнту не обов’язково чекати завершення цієї операції перед отриманням відповіді.
+
+Приклади використання:
+
+* Надсилання email-сповіщень після виконання певної дії:
+ * Підключення до поштового сервера та надсилання листа може займати кілька секунд. Ви можете відразу повернути відповідь, а email відправити у фоні.
+* Обробка даних:
+ * Наприклад, якщо отримано файл, який потрібно обробити довготривалим процесом, можна повернути відповідь "Accepted" ("Прийнято", HTTP 202) і виконати обробку файлу у фоні.
+
+## Використання `BackgroundTasks`
+
+Спочатку імпортуйте `BackgroundTasks` і додайте його як параметр у Вашу *функцію операції шляху* (path operation function) до `BackgroundTasks`:
+
+{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *}
+
+**FastAPI** автоматично створить об'єкт `BackgroundTasks` і передасть його у цей параметр.
+
+
+## Створення функції задачі
+
+Створіть функцію, яка буде виконувати фонову задачу.
+
+Це звичайна функція, яка може отримувати параметри.
+
+Вона може бути асинхронною `async def` або звичайною `def` функцією – **FastAPI** обробить її правильно.
+
+У нашому випадку функція записує у файл (імітуючи надсилання email).
+
+І оскільки операція запису не використовує `async` та `await`, ми визначаємо функцію як звичайну `def`:
+
+{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *}
+
+## Додавання фонової задачі
+
+Усередині Вашої *функції обробки шляху*, передайте функцію задачі в об'єкт *background tasks*, використовуючи метод `.add_task()`:
+
+{* ../../docs_src/background_tasks/tutorial001.py hl[14] *}
+
+`.add_task()` приймає аргументи:
+
+* Функція задача, яка буде виконуватися у фоновому режимі (`write_notification`). Зверніть увагу, що передається обʼєкт без дужок.
+* Будь-яка послідовність аргументів, які потрібно передати у функцію завдання у відповідному порядку (`email`).
+* Будь-які іменовані аргументи, які потрібно передати у функцію задачу (`message="some notification"`).
+
+## Впровадження залежностей
+
+Використання `BackgroundTasks` також працює з системою впровадження залежностей. Ви можете оголосити параметр типу `BackgroundTasks` на різних рівнях: у *функції операції шляху*, у залежності (dependable), у під залежності тощо.
+
+**FastAPI** знає, як діяти в кожному випадку і як повторно використовувати один і той самий об'єкт, щоб усі фонові задачі були об’єднані та виконувалися у фоновому режимі після завершення основного запиту.
+
+{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *}
+
+У цьому прикладі повідомлення будуть записані у файл `log.txt` *після* того, як відповідь буде надіслана.
+
+Якщо у запиті був переданий query-параметр, він буде записаний у лог у фоновій задачі.
+
+А потім інша фонова задача, яка створюється у *функції операції шляху*, запише повідомлення з використанням path параметра `email`.
+
+## Технічні деталі
+
+Клас `BackgroundTasks` походить безпосередньо з
`starlette.background`.
+
+Він імпортується безпосередньо у FastAPI, щоб Ви могли використовувати його з `fastapi` і випадково не імпортували `BackgroundTask` (без s в кінці) з `starlette.background`.
+
+Якщо використовувати лише `BackgroundTasks` (а не `BackgroundTask`), то його можна передавати як параметр у *функції операції шляху*, і **FastAPI** подбає про все інше, так само як і про використання об'єкта `Request`.
+
+Також можна використовувати `BackgroundTask` окремо в FastAPI, але для цього Вам доведеться створити об'єкт у коді та повернути Starlette `Response`, включаючи його.
+
+Детальніше можна почитати в
офіційній документації Starlette про фонові задачі .
+
+## Застереження
+
+Якщо Вам потрібно виконувати складні фонові обчислення, і при цьому нема потреби запускати їх у тому ж процесі (наприклад, не потрібно спільного доступу до пам’яті чи змінних), можливо, варто скористатися більш потужними інструментами, такими як
Celery.
+
+Такі інструменти зазвичай потребують складнішої конфігурації та менеджера черги повідомлень/завдань, наприклад, RabbitMQ або Redis. Однак вони дозволяють виконувати фонові задачі в кількох процесах і навіть на кількох серверах.
+
+Якщо ж Вам потрібно отримати доступ до змінних і об’єктів із тієї ж **FastAPI** - програми або виконувати невеликі фонові завдання (наприклад, надсилати сповіщення електронною поштою), достатньо просто використовувати `BackgroundTasks`.
+
+## Підсумок
+
+Імпортуйте та використовуйте `BackgroundTasks` як параметр у *функціях операції шляху* та залежностях, щоб додавати фонові задачі.
diff --git a/docs/uk/docs/tutorial/body-fields.md b/docs/uk/docs/tutorial/body-fields.md
new file mode 100644
index 000000000..7ddd9d104
--- /dev/null
+++ b/docs/uk/docs/tutorial/body-fields.md
@@ -0,0 +1,60 @@
+# Тіло - Поля
+
+Так само як ви можете визначати додаткову валідацію та метадані у параметрах *функції обробки шляху* за допомогою `Query`, `Path` та `Body`, ви можете визначати валідацію та метадані всередині моделей Pydantic за допомогою `Field` від Pydantic.
+
+## Імпорт `Field`
+
+Спочатку вам потрібно імпортувати це:
+
+{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[4] *}
+
+/// warning
+
+Зверніть увагу, що `Field` імпортується прямо з `pydantic`, а не з `fastapi`, як всі інші (`Query`, `Path`, `Body` тощо).
+
+///
+
+## Оголошення атрибутів моделі
+
+Ви можете використовувати `Field` з атрибутами моделі:
+
+{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[11:14] *}
+
+`Field` працює так само, як `Query`, `Path` і `Body`, у нього такі самі параметри тощо.
+
+/// note | Технічні деталі
+
+Насправді, `Query`, `Path` та інші, що ви побачите далі, створюють об'єкти підкласів загального класу `Param`, котрий сам є підкласом класу `FieldInfo` з Pydantic.
+
+І `Field` від Pydantic також повертає екземпляр `FieldInfo`.
+
+`Body` також безпосередньо повертає об'єкти підкласу `FieldInfo`. І є інші підкласи, які ви побачите пізніше, що є підкласами класу Body.
+
+Пам'ятайте, що коли ви імпортуєте 'Query', 'Path' та інше з 'fastapi', вони фактично є функціями, які повертають спеціальні класи.
+
+///
+
+/// tip
+
+Зверніть увагу, що кожен атрибут моделі із типом, значенням за замовчуванням та `Field` має ту саму структуру, що й параметр *функції обробки шляху*, з `Field` замість `Path`, `Query` і `Body`.
+
+///
+
+## Додавання додаткової інформації
+
+Ви можете визначити додаткову інформацію у `Field`, `Query`, `Body` тощо. І вона буде включена у згенеровану JSON схему.
+
+Ви дізнаєтеся більше про додавання додаткової інформації пізніше у документації, коли вивчатимете визначення прикладів.
+
+/// warning
+
+Додаткові ключі, передані в `Field`, також будуть присутні у згенерованій схемі OpenAPI для вашого додатка.
+Оскільки ці ключі не обов'язково можуть бути частиною специфікації OpenAPI, деякі інструменти OpenAPI, наприклад, [OpenAPI валідатор](https://validator.swagger.io/), можуть не працювати з вашою згенерованою схемою.
+
+///
+
+## Підсумок
+
+Ви можете використовувати `Field` з Pydantic для визначення додаткових перевірок та метаданих для атрибутів моделі.
+
+Ви також можете використовувати додаткові іменовані аргументи для передачі додаткових метаданих JSON схеми.
diff --git a/docs/uk/docs/tutorial/body-multiple-params.md b/docs/uk/docs/tutorial/body-multiple-params.md
new file mode 100644
index 000000000..e2acf8a70
--- /dev/null
+++ b/docs/uk/docs/tutorial/body-multiple-params.md
@@ -0,0 +1,170 @@
+# Тіло запиту - Декілька параметрів
+
+Тепер, коли ми розглянули використання `Path` та `Query`, розгляньмо більш просунуті способи оголошення тіла запиту в **FastAPI**.
+
+## Змішування `Path`, `Query` та параметрів тіла запиту
+
+По-перше, звісно, Ви можете вільно змішувати оголошення параметрів `Path`, `Query` та тіла запиту, і **FastAPI** правильно їх обробить.
+
+Також Ви можете оголосити параметри тіла як необов’язкові, встановивши для них значення за замовчуванням `None`:
+
+{* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *}
+
+/// note | Примітка
+
+Зверніть увагу, що в цьому випадку параметр `item`, який береться з тіла запиту, є необов'язковим, оскільки має значення за замовчуванням `None`.
+
+///
+
+## Декілька параметрів тіла запиту
+
+У попередньому прикладі *операція шляху* очікувала JSON з атрибутами `Item`, наприклад:
+
+```JSON
+{
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2
+}
+```
+Але Ви також можете оголосити декілька параметрів тіла, наприклад `item` та `user`:
+
+{* ../../docs_src/body_multiple_params/tutorial002_py310.py hl[20] *}
+
+У цьому випадку **FastAPI** розпізнає, що є кілька параметрів тіла (два параметри є моделями Pydantic).
+
+Тому він використає назви параметрів як ключі (назви полів) у тілі запиту, очікуючи:
+
+```JSON
+{
+ "item": {
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2
+ },
+ "user": {
+ "username": "dave",
+ "full_name": "Dave Grohl"
+ }
+}
+```
+
+/// note | Примітка
+
+Зверніть увагу, що хоча `item` оголошено, так само як і раніше, тепер він очікується в тілі під ключем `item`.
+
+///
+
+**FastAPI** автоматично конвертує дані із запиту таким чином, щоб параметр `item` отримав свій вміст, і те ж саме стосується `user`.
+
+Він виконає валідацію складених даних і задокументує їх відповідним чином у схемі OpenAPI та в автоматичній документації.
+
+## Одиничні значення в тілі запиту
+
+Так само як є `Query` і `Path` для визначення додаткових даних для параметрів запиту та шляху, **FastAPI** надає еквівалентний `Body`.
+
+Наприклад, розширюючи попередню модель, Ви можете вирішити додати ще один ключ `importance` в те ж саме тіло запиту разом із `item` і `user`.
+
+Якщо Ви оголосите його як є, то, оскільки це одиничне значення, **FastAPI** припускатиме, що це параметр запиту (query parameter).
+
+Але Ви можете вказати **FastAPI** обробляти його як інший ключ тіла (body key), використовуючи `Body`:
+
+{* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *}
+
+У цьому випадку **FastAPI** очікуватиме тіло запиту у такому вигляді:
+
+```JSON
+{
+ "item": {
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2
+ },
+ "user": {
+ "username": "dave",
+ "full_name": "Dave Grohl"
+ },
+ "importance": 5
+}
+```
+Знову ж таки, **FastAPI** конвертуватиме типи даних, перевірятиме їх, створюватиме документацію тощо.
+
+## Декілька body та query параметрів
+
+Звісно, Ви можете оголошувати додаткові query параметри запиту, коли це необхідно, на додаток до будь-яких параметрів тіла запиту.
+
+Оскільки за замовчуванням окремі значення інтерпретуються як параметри запиту, Вам не потрібно явно додавати `Query`, можна просто використати:
+
+```Python
+q: Union[str, None] = None
+```
+
+Або в Python 3.10 та вище:
+
+```Python
+q: str | None = None
+```
+
+Наприклад:
+
+{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *}
+
+
+/// info | Інформація
+
+`Body` також має ті самі додаткові параметри валідації та метаданих, що й `Query`, `Path` та інші, які Ви побачите пізніше.
+
+///
+
+## Вкладений поодинокий параметр тіла запиту
+
+Припустимо, у вас є лише один параметр тіла запиту `item` з моделі Pydantic `Item`.
+
+За замовчуванням **FastAPI** очікуватиме, що тіло запиту міститиме вміст безпосередньо.
+
+Але якщо Ви хочете, щоб він очікував JSON з ключем `item`, а всередині — вміст моделі (так, як це відбувається при оголошенні додаткових параметрів тіла), Ви можете використати спеціальний параметр `Body` — `embed`:
+
+```Python
+item: Item = Body(embed=True)
+```
+
+як у прикладі:
+
+{* ../../docs_src/body_multiple_params/tutorial005_an_py310.py hl[17] *}
+
+У цьому випадку **FastAPI** очікуватиме тіло запиту такого вигляду:
+
+```JSON hl_lines="2"
+{
+ "item": {
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2
+ }
+}
+```
+
+замість:
+
+```JSON
+{
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2
+}
+```
+
+## Підсумок
+
+Ви можете додавати кілька параметрів тіла до Вашої *функції операції шляху* (*path operation function*), навіть якщо запит може мати лише одне тіло.
+
+Але **FastAPI** обробить це, надасть Вам потрібні дані у функції, перевірить їх та задокументує коректну схему в *операції шляху*.
+
+Також Ви можете оголошувати окремі значення, які будуть отримані як частина тіла запиту.
+
+Крім того, Ви можете вказати **FastAPI** вбудовувати тіло в ключ, навіть якщо оголошено лише один параметр.
diff --git a/docs/uk/docs/tutorial/body-nested-models.md b/docs/uk/docs/tutorial/body-nested-models.md
new file mode 100644
index 000000000..abc33f2eb
--- /dev/null
+++ b/docs/uk/docs/tutorial/body-nested-models.md
@@ -0,0 +1,245 @@
+# Тіло запиту - Вкладені моделі
+
+З **FastAPI** Ви можете визначати, перевіряти, документувати та використовувати моделі, які можуть бути вкладені на будь-яку глибину (завдяки Pydantic).
+
+## Поля списку
+
+Ви можете визначити атрибут як підтип. Наприклад, Python-список (`list`):
+
+{* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *}
+
+Це зробить `tags` списком, хоча не визначається тип елементів списку.
+
+## Поля списку з параметром типу
+
+Але Python має специфічний спосіб оголошення списків з внутрішніми типами або "параметрами типу":
+### Імпортуємо `List` з модуля typing
+
+У Python 3.9 і вище можна використовувати стандартний `list` для оголошення таких типів, як ми побачимо нижче. 💡
+
+Але в Python версії до 3.9 (від 3.6 і вище) спочатку потрібно імпортувати `List` з модуля стандартної бібліотеки Python `typing`:
+
+{* ../../docs_src/body_nested_models/tutorial002.py hl[1] *}
+
+### Оголошення `list` з параметром типу
+
+Щоб оголосити типи з параметрами типу (внутрішніми типами), такими як `list`, `dict`, `tuple`:
+
+* Якщо Ви використовуєте версію Python до 3.9, імпортуйте їх відповідну версію з модуля `typing`.
+* Передайте внутрішні типи як "параметри типу", використовуючи квадратні дужки: `[` and `]`.
+
+У Python 3.9 це буде виглядати так:
+
+```Python
+my_list: list[str]
+```
+
+У версіях Python до 3.9 це виглядає так:
+
+```Python
+from typing import List
+
+my_list: List[str]
+```
+
+Це стандартний синтаксис Python для оголошення типів.
+
+Використовуйте той самий стандартний синтаксис для атрибутів моделей з внутрішніми типами.
+
+Отже, у нашому прикладі, ми можемо зробити `tags` саме "списком рядків":
+
+{* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *}
+
+## Типи множин
+
+Але потім ми подумали, що теги не повинні повторюватися, вони, ймовірно, повинні бути унікальними рядками.
+
+І Python має спеціальний тип даних для множин унікальних елементів — це `set`.
+
+Тому ми можемо оголосити `tags` як множину рядків:
+
+{* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *}
+
+Навіть якщо Ви отримаєте запит з дубльованими даними, він буде перетворений у множину унікальних елементів.
+
+І коли Ви будете виводити ці дані, навіть якщо джерело містить дублікати, вони будуть виведені як множина унікальних елементів.
+
+І це буде анотовано/документовано відповідно.
+
+## Вкладені моделі
+
+Кожен атрибут моделі Pydantic має тип.
+
+Але цей тип сам може бути іншою моделлю Pydantic.
+
+Отже, Ви можете оголосити глибоко вкладені JSON "об'єкти" з конкретними іменами атрибутів, типами та перевірками.
+
+Усе це, вкладене без обмежень.
+
+### Визначення підмоделі
+
+Наприклад, ми можемо визначити модель `Image`:
+
+{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *}
+
+### Використання підмоделі як типу
+
+А потім ми можемо використовувати її як тип атрибута:
+
+{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *}
+
+Це означатиме, що **FastAPI** очікуватиме тіло запиту такого вигляду:
+
+```JSON
+{
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2,
+ "tags": ["rock", "metal", "bar"],
+ "image": {
+ "url": "http://example.com/baz.jpg",
+ "name": "The Foo live"
+ }
+}
+```
+
+Завдяки такій декларації у **FastAPI** Ви отримуєте:
+
+* Підтримку в редакторі (автозавершення тощо), навіть для вкладених моделей
+* Конвертацію даних
+* Валідацію даних
+* Автоматичну документацію
+
+## Спеціальні типи та валідація
+
+Окрім звичайних типів, таких як `str`, `int`, `float`, та ін. Ви можете використовувати складніші типи, які наслідують `str`.
+
+Щоб побачити всі доступні варіанти, ознайомтеся з оглядом
типів у Pydantic. Деякі приклади будуть у наступних розділах.
+
+Наприклад, у моделі `Image` є поле `url`, тому ми можемо оголосити його як `HttpUrl` від Pydantic замість `str`:
+
+{* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *}
+
+Рядок буде перевірено як дійсну URL-адресу і задокументовано в JSON Schema / OpenAPI як URL.
+
+## Атрибути зі списками підмоделей
+
+У Pydantic Ви можете використовувати моделі як підтипи для `list`, `set` тощо:
+
+{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *}
+
+Це означає, що **FastAPI** буде очікувати (конвертувати, валідувати, документувати тощо) JSON тіло запиту у вигляді:
+
+```JSON hl_lines="11"
+{
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2,
+ "tags": [
+ "rock",
+ "metal",
+ "bar"
+ ],
+ "images": [
+ {
+ "url": "http://example.com/baz.jpg",
+ "name": "The Foo live"
+ },
+ {
+ "url": "http://example.com/dave.jpg",
+ "name": "The Baz"
+ }
+ ]
+}
+```
+
+/// info | Інформація
+
+Зверніть увагу, що тепер ключ `images` містить список об'єктів зображень.
+
+///
+
+## Глибоко вкладені моделі
+
+Ви можете визначати вкладені моделі довільної глибини:
+
+{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *}
+
+/// info | Інформація
+
+Зверніть увагу, що в моделі `Offer` є список `Item`ів, які, своєю чергою, можуть мати необов'язковий список `Image`ів.
+
+///
+
+## Тіла запитів, що складаються зі списків
+
+Якщо верхній рівень JSON тіла, яке Ви очікуєте, є JSON `масивом` (у Python — `list`), Ви можете оголосити тип у параметрі функції, як і в моделях Pydantic:
+
+```Python
+images: List[Image]
+```
+або в Python 3.9 і вище:
+
+```Python
+images: list[Image]
+```
+
+наприклад:
+
+{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *}
+
+## Підтримка в редакторі всюди
+
+Ви отримаєте підтримку в редакторі всюди.
+
+Навіть для елементів у списках:
+
+

+
+Ви не змогли б отримати таку підтримку в редакторі, якби працювали напряму зі `dict`, а не з моделями Pydantic.
+
+Але Вам не потрібно турбуватися про це: вхідні dict'и автоматично конвертуються, а вихідні дані автоматично перетворюються в JSON.
+
+## Тіла з довільними `dict`
+
+Ви також можете оголосити тіло як `dict` з ключами одного типу та значеннями іншого типу.
+
+Це корисно, якщо Ви не знаєте наперед, які імена полів будуть дійсними (як у випадку з моделями Pydantic).
+
+Це буде корисно, якщо Ви хочете приймати ключі, які заздалегідь невідомі.
+
+---
+
+Це також зручно, якщо Ви хочете мати ключі іншого типу (наприклад, `int`).
+
+Ось що ми розглянемо далі.
+
+У цьому випадку Ви можете приймати будь-який `dict`, якщо його ключі — це `int`, а значення — `float`:
+
+{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *}
+
+/// tip | Порада
+
+Майте на увазі, що в JSON тілі ключі можуть бути лише рядками (`str`).
+
+Але Pydantic автоматично конвертує дані.
+
+Це означає, що навіть якщо клієнти вашого API надсилатимуть ключі у вигляді рядків, якщо вони містять цілі числа, Pydantic конвертує їх і проведе валідацію.
+
+Тобто `dict`, який Ви отримаєте як `weights`, матиме ключі типу `int` та значення типу `float`.
+
+///
+
+## Підсумок
+
+З **FastAPI** Ви маєте максимальну гнучкість завдяки моделям Pydantic, зберігаючи при цьому код простим, коротким та елегантним.
+
+А також отримуєте всі переваги:
+
+* Підтримка в редакторі (автодоповнення всюди!)
+* Конвертація даних (парсинг/сериалізація)
+* Валідація даних
+* Документація схем
+* Автоматичне створення документації
diff --git a/docs/uk/docs/tutorial/body-updates.md b/docs/uk/docs/tutorial/body-updates.md
new file mode 100644
index 000000000..e78b5a5bf
--- /dev/null
+++ b/docs/uk/docs/tutorial/body-updates.md
@@ -0,0 +1,116 @@
+# Тіло – Оновлення
+
+## Оновлення з використанням `PUT`
+
+Щоб оновити елемент, Ви можете використати
HTTP `PUT` операцію.
+
+Ви можете використати `jsonable_encoder`, щоб перетворити вхідні дані на такі, які можна зберігати як JSON (наприклад, у NoSQL базі даних). Наприклад, перетворюючи `datetime` у `str`.
+
+{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *}
+
+`PUT` використовується для отримання даних, які мають замінити чинні дані.
+
+### Попередження про заміну
+
+Це означає, що якщо Ви хочете оновити елемент `bar`, використовуючи `PUT` з тілом:
+
+```Python
+{
+ "name": "Barz",
+ "price": 3,
+ "description": None,
+}
+```
+
+оскільки він не містить вже збереженого атрибута `"tax": 20.2`, модель введення прийме значення за замовчуванням `"tax": 10.5`.
+
+І дані будуть збережені з цим "новим" значенням `tax` = `10.5`.
+
+## Часткові оновлення з `PATCH`
+
+Ви також можете використовувати операцію
HTTP `PATCH` для *часткового* оновлення даних.
+
+Це означає, що Ви можете надіслати лише ті дані, які хочете оновити, залишаючи інші без змін.
+
+/// note | Примітка
+
+`PATCH` менш відомий і рідше використовується, ніж `PUT`.
+
+І багато команд використовують лише `PUT`, навіть для часткових оновлень.
+
+Ви **вільні** використовувати їх так, як хочете, **FastAPI** не накладає обмежень.
+
+Але цей посібник показує Вам більш-менш як їх задумано використовувати.
+
+///
+
+### Використання параметра `exclude_unset` у Pydantic
+
+Якщо Ви хочете отримати часткові оновлення, дуже зручно використовувати параметр `exclude_unset` у методі `.model_dump()` моделі Pydantic.
+
+Наприклад: `item.model_dump(exclude_unset=True)`.
+
+/// info | Інформація
+
+У Pydantic v1 цей метод називався `.dict()`, він був застарілий (але все ще підтримується) у Pydantic v2, і був перейменований у `.model_dump()`.
+
+Приклади тут використовують `.dict()` для сумісності з Pydantic v1, але Вам слід використовувати `.model_dump()`, якщо можете використовувати Pydantic v2.
+
+///
+
+Це створить `dict` лише з тими даними, які були явно встановлені під час створення моделі `item`, виключаючи значення за замовчуванням.
+
+Тоді Ви можете використовувати це, щоб створити `dict` лише з даними, які були встановлені (надіслані у запиті), пропускаючи значення за замовчуванням:
+
+{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *}
+
+### Використання параметра `update` у Pydantic
+
+Тепер Ви можете створити копію наявної моделі за допомогою `.model_copy()`, і передати параметр `update` з `dict` , який містить дані для оновлення.
+
+/// info | Інформація
+
+У Pydantic v1 метод називався `.copy()`, він був застарілий (але все ще підтримується) у Pydantic v2, і був перейменований у `.model_copy()`.
+
+Приклади тут використовують `.copy()` для сумісності з Pydantic v1, але якщо Ви можете використовувати Pydantic v2 — Вам слід використовувати `.model_copy()` замість цього.
+
+///
+
+Наприклад: `stored_item_model.model_copy(update=update_data)`:
+
+{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *}
+
+### Підсумок часткових оновлень
+
+У підсумку, щоб застосувати часткові оновлення, Ви:
+
+* (Опціонально) використовуєте `PATCH` замість `PUT`.
+* Отримуєте збережені дані.
+* Поміщаєте ці дані в модель Pydantic.
+* Генеруєте `dict` без значень за замовчуванням з моделі введення (використовуючи `exclude_unset`).
+ * Таким чином Ви оновите лише ті значення, які були явно задані користувачем, замість того, щоб перезаписувати вже збережені значення значеннями за замовчуванням з вашої моделі.
+* Створюєте копію збереженої моделі, оновлюючи її атрибути отриманими частковими оновленнями (використовуючи параметр `update`).
+* Перетворюєте скопійовану модель на щось, що можна зберегти у вашу БД (наприклад, використовуючи `jsonable_encoder`).
+ * Це можна порівняти з повторним використанням методу `.model_dump()` моделі, але це гарантує (і перетворює) значення у типи даних, які можна перетворити на JSON, наприклад, `datetime` на `str`.
+* Зберігаєте дані у вашу БД.
+* Повертаєте оновлену модель.
+
+{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *}
+
+/// tip | Порада
+
+Насправді Ви можете використовувати цю саму техніку і з операцією HTTP `PUT`.
+
+Але приклад тут використовує `PATCH`, тому що він був створений саме для таких випадків.
+
+///
+
+/// note | Примітка
+
+Зверніть увагу, що модель запиту все ще проходить валідацію.
+
+Тож, якщо Ви хочете отримувати часткові оновлення, які можуть не містити жодного атрибута, Вам потрібно мати модель, де всі атрибути позначені як необов’язкові (зі значеннями за замовчуванням або `None`).
+
+Щоб розрізняти моделі з усіма необов’язковими значеннями для **оновлення** і моделі з обов’язковими значеннями для **створення**, Ви можете скористатись ідеями, описаними у [Додаткові моделі](extra-models.md){.internal-link target=_blank}.
+
+///
diff --git a/docs/uk/docs/tutorial/body.md b/docs/uk/docs/tutorial/body.md
new file mode 100644
index 000000000..38fed7bb8
--- /dev/null
+++ b/docs/uk/docs/tutorial/body.md
@@ -0,0 +1,162 @@
+# Тіло запиту
+
+Коли вам потрібно надіслати дані з клієнта (скажімо, браузера) до вашого API, ви надсилаєте їх як **тіло запиту**.
+
+Тіло **запиту** — це дані, надіслані клієнтом до вашого API. Тіло **відповіді** — це дані, які ваш API надсилає клієнту.
+
+Ваш API майже завжди має надсилати тіло **відповіді**. Але клієнтам не обов’язково потрібно постійно надсилати тіла **запитів**.
+
+Щоб оголосити тіло **запиту**, ви використовуєте
Pydantic моделі з усією їх потужністю та перевагами.
+
+/// info
+
+Щоб надіслати дані, ви повинні використовувати один із: `POST` (більш поширений), `PUT`, `DELETE` або `PATCH`.
+
+Надсилання тіла із запитом `GET` має невизначену поведінку в специфікаціях, проте воно підтримується FastAPI лише для дуже складних/екстремальних випадків використання.
+
+Оскільки це не рекомендується, інтерактивна документація з Swagger UI не відображатиме документацію для тіла запиту під час використання `GET`, і проксі-сервери в середині можуть не підтримувати її.
+
+///
+
+## Імпортуйте `BaseModel` від Pydantic
+
+Спочатку вам потрібно імпортувати `BaseModel` з `pydantic`:
+
+{* ../../docs_src/body/tutorial001.py hl[4] *}
+
+## Створіть свою модель даних
+
+Потім ви оголошуєте свою модель даних як клас, який успадковується від `BaseModel`.
+
+Використовуйте стандартні типи Python для всіх атрибутів:
+
+{* ../../docs_src/body/tutorial001.py hl[7:11] *}
+
+Так само, як і при оголошенні параметрів запиту, коли атрибут моделі має значення за замовчуванням, він не є обов’язковим. В іншому випадку це потрібно. Використовуйте `None`, щоб зробити його необов'язковим.
+
+Наприклад, ця модель вище оголошує JSON "`об'єкт`" (або Python `dict`), як:
+
+```JSON
+{
+ "name": "Foo",
+ "description": "An optional description",
+ "price": 45.2,
+ "tax": 3.5
+}
+```
+
+...оскільки `description` і `tax` є необов'язковими (зі значенням за замовчуванням `None`), цей JSON "`об'єкт`" також буде дійсним:
+
+```JSON
+{
+ "name": "Foo",
+ "price": 45.2
+}
+```
+
+## Оголоси її як параметр
+
+Щоб додати модель даних до вашої *операції шляху*, оголосіть її так само, як ви оголосили параметри шляху та запиту:
+
+{* ../../docs_src/body/tutorial001.py hl[18] *}
+
+...і вкажіть її тип як модель, яку ви створили, `Item`.
+
+## Результати
+
+Лише з цим оголошенням типу Python **FastAPI** буде:
+
+* Читати тіло запиту як JSON.
+* Перетворювати відповідні типи (якщо потрібно).
+* Валідувати дані.
+ * Якщо дані недійсні, він поверне гарну та чітку помилку, вказуючи, де саме і які дані були неправильними.
+* Надавати отримані дані у параметрі `item`.
+ * Оскільки ви оголосили його у функції як тип `Item`, ви також матимете всю підтримку редактора (автозаповнення, тощо) для всіх атрибутів та їх типів.
+* Генерувати
JSON Schema визначення для вашої моделі, ви також можете використовувати їх де завгодно, якщо це має сенс для вашого проекту.
+* Ці схеми будуть частиною згенерованої схеми OpenAPI і використовуватимуться автоматичною документацією інтерфейсу користувача.
+
+## Автоматична документація
+
+Схеми JSON ваших моделей будуть частиною вашої схеми, згенерованої OpenAPI, і будуть показані в інтерактивній API документації:
+
+

+
+А також використовуватимуться в API документації всередині кожної *операції шляху*, якій вони потрібні:
+
+

+
+## Підтримка редактора
+
+У вашому редакторі, всередині вашої функції, ви будете отримувати підказки типу та завершення скрізь (це б не сталося, якби ви отримали `dict` замість моделі Pydantic):
+
+

+
+Ви також отримуєте перевірку помилок на наявність операцій з неправильним типом:
+
+

+
+Це не випадково, весь каркас був побудований навколо цього дизайну.
+
+І він був ретельно перевірений на етапі проектування, перед будь-яким впровадженням, щоб переконатися, що він працюватиме з усіма редакторами.
+
+Були навіть деякі зміни в самому Pydantic, щоб підтримати це.
+
+Попередні скріншоти були зроблені у
Visual Studio Code.
+
+Але ви отримаєте ту саму підтримку редактора у
PyCharm та більшість інших редакторів Python:
+
+

+
+/// tip
+
+Якщо ви використовуєте
PyCharm як ваш редактор, ви можете використати
Pydantic PyCharm Plugin.
+
+Він покращує підтримку редакторів для моделей Pydantic за допомогою:
+
+* автозаповнення
+* перевірки типу
+* рефакторингу
+* пошуку
+* інспекції
+
+///
+
+## Використовуйте модель
+
+Усередині функції ви можете отримати прямий доступ до всіх атрибутів об’єкта моделі:
+
+{* ../../docs_src/body/tutorial002.py hl[21] *}
+
+## Тіло запиту + параметри шляху
+
+Ви можете одночасно оголошувати параметри шляху та тіло запиту.
+
+**FastAPI** розпізнає, що параметри функції, які відповідають параметрам шляху, мають бути **взяті з шляху**, а параметри функції, які оголошуються як моделі Pydantic, **взяті з тіла запиту**.
+
+{* ../../docs_src/body/tutorial003.py hl[17:18] *}
+
+## Тіло запиту + шлях + параметри запиту
+
+Ви також можете оголосити параметри **тіло**, **шлях** і **запит** одночасно.
+
+**FastAPI** розпізнає кожен з них і візьме дані з потрібного місця.
+
+{* ../../docs_src/body/tutorial004.py hl[18] *}
+
+Параметри функції будуть розпізнаватися наступним чином:
+
+* Якщо параметр також оголошено в **шляху**, він використовуватиметься як параметр шляху.
+* Якщо параметр має **сингулярний тип** (наприклад, `int`, `float`, `str`, `bool` тощо), він буде інтерпретуватися як параметр **запиту**.
+* Якщо параметр оголошується як тип **Pydantic моделі**, він інтерпретується як **тіло** запиту.
+
+/// note
+
+FastAPI буде знати, що значення "q" не є обов'язковим через значення за замовчуванням "= None".
+
+`Optional` у `Optional[str]` не використовується FastAPI, але дозволить вашому редактору надати вам кращу підтримку та виявляти помилки.
+
+///
+
+## Без Pydantic
+
+Якщо ви не хочете використовувати моделі Pydantic, ви також можете використовувати параметри **Body**. Перегляньте документацію для [Тіло – Кілька параметрів: сингулярні значення в тілі](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
diff --git a/docs/uk/docs/tutorial/cookie-param-models.md b/docs/uk/docs/tutorial/cookie-param-models.md
new file mode 100644
index 000000000..f070b6ac8
--- /dev/null
+++ b/docs/uk/docs/tutorial/cookie-param-models.md
@@ -0,0 +1,76 @@
+# Моделі для Cookie-параметрів
+
+Якщо у Вас є група **cookies** параметрів, які пов'язані між собою, Ви можете створити **Pydantic-модель**, щоб оголосити їх. 🍪
+
+Це дозволить Вам повторно **використовувати модель** у **різних місцях**, а також оголосити валідацію та метадані для всіх параметрів одночасно. 😎
+
+/// note | Нотатки
+
+Це підтримується з версії FastAPI `0.115.0`. 🤓
+
+///
+
+/// tip | Порада
+
+Ця ж техніка застосовується до `Query`, `Cookie`, та `Header`. 😎
+
+///
+
+## Cookie з Pydantic-моделлю
+
+Оголосіть **cookie-параметри**, які Вам потрібні, у **Pydantic-моделі**, а потім оголосіть параметр як `Cookie`:
+
+{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *}
+
+**FastAPI** буде **витягувати** дані для **кожного поля** з **cookie** параметрів, отриманих у запиті, і передавати Вам Pydantic-модель, яку Ви визначили.
+
+## Перевірка у документації
+
+Ви можете побачити визначені cookie в інтерфейсі документації за адресою `/docs`:
+
+
+

+
+
+/// info | Інформація
+
+Майте на увазі, що оскільки **браузери обробляють cookie** особливим чином і "за лаштунками", вони **не** дозволяють **JavaScript** легко з ними працювати.
+
+Якщо Ви зайдете до **інтерфейсу документації API** за адресою `/docs`, Ви зможете побачити **документацію** для cookie у Ваших **операціях шляху**.
+
+Але навіть якщо Ви заповните дані й натиснете "Execute", оскільки інтерфейс документації працює з **JavaScript**, cookie не будуть відправлені, і Ви побачите **помилку**, ніби Ви не ввели жодних значень.
+
+///
+
+## Заборона додаткових cookie
+
+У деяких спеціальних випадках (ймовірно, не дуже поширених) Ви можете захотіти **обмежити** список cookie, які хочете отримувати.
+
+Ваша API тепер має можливість контролювати власну
згоду на cookie. 🤪🍪
+
+Ви можете використовувати налаштування моделі Pydantic, щоб `заборонити` будь-які `додаткові` поля:
+
+{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *}
+
+Якщо клієнт спробує надіслати якісь **додаткові cookie**, він отримає відповідь з **помилкою**.
+
+Бідні банери cookie, які так старанно намагаються отримати Вашу згоду, щоб
API її відхилила. 🍪
+
+Наприклад, якщо клієнт спробує надіслати cookie `santa_tracker` зі значенням `good-list-please`, він отримає відповідь з помилкою, яка повідомить, що
cookie `santa_tracker` не дозволено:
+
+```json
+{
+ "detail": [
+ {
+ "type": "extra_forbidden",
+ "loc": ["cookie", "santa_tracker"],
+ "msg": "Extra inputs are not permitted",
+ "input": "good-list-please",
+ }
+ ]
+}
+```
+
+## Підсумок
+
+Ви можете використовувати **Pydantic-моделі** для оголошення
cookie у FastAPI. 😎
diff --git a/docs/uk/docs/tutorial/cookie-params.md b/docs/uk/docs/tutorial/cookie-params.md
new file mode 100644
index 000000000..b320645cb
--- /dev/null
+++ b/docs/uk/docs/tutorial/cookie-params.md
@@ -0,0 +1,34 @@
+# Параметри Cookie
+
+Ви можете визначити параметри Cookie таким же чином, як визначаються параметри `Query` і `Path`.
+
+## Імпорт `Cookie`
+
+Спочатку імпортуйте `Cookie`:
+
+{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *}
+
+## Визначення параметрів `Cookie`
+
+Потім визначте параметри cookie, використовуючи таку ж конструкцію як для `Path` і `Query`.
+
+Перше значення це значення за замовчуванням, ви можете також передати всі додаткові параметри валідації чи анотації:
+
+{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *}
+
+/// note | Технічні Деталі
+
+`Cookie` це "сестра" класів `Path` і `Query`. Вони наслідуються від одного батьківського класу `Param`.
+Але пам'ятайте, що коли ви імпортуєте `Query`, `Path`, `Cookie` та інше з `fastapi`, це фактично функції, що повертають спеціальні класи.
+
+///
+
+/// info
+
+Для визначення cookies ви маєте використовувати `Cookie`, тому що в іншому випадку параметри будуть інтерпритовані, як параметри запиту.
+
+///
+
+## Підсумки
+
+Визначайте cookies за допомогою `Cookie`, використовуючи той же спільний шаблон, що і `Query` та `Path`.
diff --git a/docs/uk/docs/tutorial/cors.md b/docs/uk/docs/tutorial/cors.md
new file mode 100644
index 000000000..95b204d0f
--- /dev/null
+++ b/docs/uk/docs/tutorial/cors.md
@@ -0,0 +1,89 @@
+# CORS (Обмін ресурсами між різними джерелами)
+
+
CORS або "Обмін ресурсами між різними джерелами" є ситуація, коли фронтенд, що працює в браузері, містить JavaScript-код, який взаємодіє з бекендом, розташованим в іншому "джерелі" (origin).
+
+## Джерело (Origin)
+
+Джерело визначається комбінацією протоколу (`http`, `https`), домену (`myapp.com`, `localhost`, `localhost.tiangolo.com`), порту (`80`, `443`, `8080`).
+
+
+Наприклад, такі адреси вважаються різними джерелами:
+
+* `http://localhost`
+* `https://localhost`
+* `http://localhost:8080`
+
+Навіть якщо вони всі містять `localhost`, вони мають різні протоколи або порти, що робить їх окремими "джерелами".
+
+## Кроки
+
+Припустимо, що Ваш фронтенд працює в браузері на `http://localhost:8080`, а його JavaScript намагається відправити запит до бекенду, який працює на `http://localhost` (Оскільки ми не вказуємо порт, браузер за замовчуванням припускає порт `80`).
+
+Потім браузер надішле HTTP-запит `OPTIONS` до бекенду на порту `:80`, і якщо бекенд надішле відповідні заголовки, що дозволяють комунікацію з цього іншого джерела (`http://localhost:8080`), тоді браузер на порту `:8080` дозволить JavaScript у фронтенді надіслати свій запит до бекенду на порту `:80`.
+
+Щоб досягти цього, бекенд на порту `:80` повинен мати список "дозволених джерел".
+
+У цьому випадку список має містити `http://localhost:8080`, щоб фронтенд на порту `:8080` працював коректно.
+
+## Символьне підставляння
+
+Можна також оголосити список як `"*"` ("символьне підставляння"), що означає дозвіл для всіх джерел.
+
+Однак це дозволить лише певні типи комунікації, виключаючи все, що пов'язане з обліковими даними: Cookies, заголовки авторизації, такі як ті, що використовуються з Bearer токенами тощо.
+
+Тому для коректної роботи краще явно вказувати дозволені джерела.
+
+## Використання `CORSMiddleware`
+
+Ви можете налаштувати це у Вашому додатку **FastAPI** за допомогою `CORSMiddleware`.
+
+* Імпортуйте `CORSMiddleware`.
+* Створіть список дозволених джерел (у вигляді рядків).
+* Додайте його як "middleware" у Ваш додаток **FastAPI**.
+
+
+Також можна вказати, чи дозволяє Ваш бекенд:
+
+* Облікові дані (заголовки авторизації, сookies, тощо).
+* Конкретні HTTP-методи (`POST`, `PUT`) або всі за допомогою `"*"`
+* Конкретні HTTP-заголовки або всі за допомогою `"*"`.
+
+
+{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *}
+
+Параметри за замовчуванням у `CORSMiddleware` є досить обмеженими, тому Вам потрібно явно вказати конкретні джерела, методи або заголовки, щоб браузери могли використовувати їх у контексті запитів між різними доменами.
+
+
+Підтримуються такі аргументи:
+
+* `allow_origins` - Список джерел, яким дозволено здійснювати міждоменні запити. Наприклад `['https://example.org', 'https://www.example.org']`. Ви можете використовувати ['*'], щоб дозволити всі джерела.
+* `allow_origin_regex` - Рядок регулярного виразу для відповідності джерелам, яким дозволено здійснювати міждоменні запити. Наприклад, `'https://.*\.example\.org'`.
+* `allow_methods` - Список HTTP-методів, дозволених для міждоменних запитів. За замовчуванням `['GET']`. Ви можете використовувати `['*']`, щоб дозволити всі стандартні методи.
+* `allow_headers` - Список HTTP-заголовків, які підтримуються для міждоменних запитів. За замовчуванням `[]`. Ви можете використовувати `['*']`, щоб дозволити всі заголовки. Заголовки `Accept`, `Accept-Language`, `Content-Language` і `Content-Type` завжди дозволені для
простих CORS-запитів.
+* `allow_credentials` - Визначає, чи підтримуються файли cookie для міждоменних запитів. За замовчуванням `False`. Також, якщо потрібно дозволити обмін обліковими даними (`allow_credentials = True`), параметр `allow_origins` не може бути встановлений як `['*']`, необхідно вказати конкретні джерела.
+* `expose_headers` - Вказує, які заголовки відповіді повинні бути доступні для браузера. За замовчуванням `[]`.
+* `max_age` - Встановлює максимальний час (у секундах) для кешування CORS-відповідей у браузерах. За замовчуванням `600`.
+
+Цей middleware обробляє два типи HTTP-запитів...
+
+### Попередні CORS-запити (preflight requests)
+
+Це будь-які `OPTIONS` - запити, що містять заголовки `Origin` та `Access-Control-Request-Method`.
+
+У такому випадку middleware перехопить вхідний запит і відповість відповідними CORS-заголовками, повертаючи або `200`, або `400` для інформаційних цілей.
+
+### Прості запити
+
+Будь-які запити із заголовком `Origin`. У цьому випадку middleware пропустить запит як звичайний, але додасть відповідні CORS-заголовки у відповідь.
+
+## Додаткова інформація
+
+Більше про
CORS можна дізнатися в
документації Mozilla.
+
+/// note | Технічні деталі
+
+Також можна використовувати `from starlette.middleware.cors import CORSMiddleware`.
+
+**FastAPI** надає кілька middleware у `fastapi.middleware` для зручності розробників. Але більшість доступних middleware походять безпосередньо зі Starlette.
+
+///
diff --git a/docs/uk/docs/tutorial/debugging.md b/docs/uk/docs/tutorial/debugging.md
new file mode 100644
index 000000000..b0e5344f8
--- /dev/null
+++ b/docs/uk/docs/tutorial/debugging.md
@@ -0,0 +1,112 @@
+# Налагодження (Debugging)
+
+Ви можете під'єднати дебагер у Вашому редакторі коду, наприклад, у Visual Studio Code або PyCharm.
+
+## Виклик `uvicorn`
+
+У Вашому FastAPI-додатку імпортуйте та запустіть `uvicorn` безпосередньо:
+
+{* ../../docs_src/debugging/tutorial001.py hl[1,15] *}
+
+### Про `__name__ == "__main__"`
+
+Головна мета використання `__name__ == "__main__"` — це забезпечення виконання певного коду тільки тоді, коли файл запускається безпосередньо:
+
+
+
+```console
+$ python myapp.py
+```
+
+
+
+але не виконується при його імпорті в інший файл, наприклад:
+
+```Python
+from myapp import app
+```
+
+#### Детальніше
+
+Припустимо, Ваш файл називається `myapp.py`.
+
+Якщо Ви запустите його так:
+
+
+
+```console
+$ python myapp.py
+```
+
+
+
+тоді внутрішня змінна `__name__`, яка створюється автоматично Python, матиме значення `"__main__"`.
+
+Отже, цей блок коду:
+
+```Python
+ uvicorn.run(app, host="0.0.0.0", port=8000)
+```
+
+буде виконаний.
+
+---
+
+Це не станеться, якщо Ви імпортуєте цей модуль (файл).
+
+Якщо у Вас є інший файл, наприклад `importer.py`, з наступним кодом:
+
+```Python
+from myapp import app
+
+# Додатковий код
+```
+
+У цьому випадку автоматично створена змінна у файлі `myapp.py` не матиме значення змінної `__name__` як `"__main__"`.
+
+Отже, рядок:
+
+```Python
+ uvicorn.run(app, host="0.0.0.0", port=8000)
+```
+
+не буде виконано.
+
+/// info | Інформація
+
+Більш детальну інформацію можна знайти в
офіційній документації Python.
+
+///
+
+## Запуск коду з вашим дебагером
+
+Оскільки Ви запускаєте сервер Uvicorn безпосередньо з Вашого коду, Ви можете запустити вашу Python програму (ваш FastAPI додаток) безпосередньо з дебагера.
+
+---
+
+Наприклад, у Visual Studio Code Ви можете:
+
+* Перейдіть на вкладку "Debug".
+* Натисніть "Add configuration...".
+* Виберіть "Python"
+* Запустіть дебагер з опцією "`Python: Current File (Integrated Terminal)`".
+
+Це запустить сервер з Вашим **FastAPI** кодом, зупиниться на точках зупину тощо.
+
+Ось як це може виглядати:
+
+

+
+---
+Якщо Ви використовуєте PyCharm, ви можете:
+
+* Відкрити меню "Run".
+* Вибрати опцію "Debug...".
+* Потім з'явиться контекстне меню.
+* Вибрати файл для налагодження (у цьому випадку, `main.py`).
+
+Це запустить сервер з Вашим **FastAPI** кодом, зупиниться на точках зупину тощо.
+
+Ось як це може виглядати:
+
+

diff --git a/docs/uk/docs/tutorial/encoder.md b/docs/uk/docs/tutorial/encoder.md
new file mode 100644
index 000000000..f202c7989
--- /dev/null
+++ b/docs/uk/docs/tutorial/encoder.md
@@ -0,0 +1,35 @@
+# JSON Compatible Encoder
+
+Існують випадки, коли вам може знадобитися перетворити тип даних (наприклад, модель Pydantic) в щось сумісне з JSON (наприклад, `dict`, `list`, і т. д.).
+
+Наприклад, якщо вам потрібно зберегти це в базі даних.
+
+Для цього, **FastAPI** надає `jsonable_encoder()` функцію.
+
+## Використання `jsonable_encoder`
+
+Давайте уявимо, що у вас є база даних `fake_db`, яка приймає лише дані, сумісні з JSON.
+
+Наприклад, вона не приймає об'єкти типу `datetime`, оскільки вони не сумісні з JSON.
+
+Отже, об'єкт типу `datetime` потрібно перетворити в рядок `str`, який містить дані в
ISO форматі.
+
+Тим самим способом ця база даних не прийматиме об'єкт типу Pydantic model (об'єкт з атрибутами), а лише `dict`.
+
+Ви можете використовувати `jsonable_encoder` для цього.
+
+Вона приймає об'єкт, такий як Pydantic model, і повертає його версію, сумісну з JSON:
+
+{* ../../docs_src/encoder/tutorial001_py310.py hl[4,21] *}
+
+У цьому прикладі вона конвертує Pydantic model у `dict`, а `datetime` у `str`.
+
+Результат виклику цієї функції - це щось, що можна кодувати з використанням стандарту Python
`json.dumps()`.
+
+Вона не повертає велику строку `str`, яка містить дані у форматі JSON (як строка). Вона повертає стандартну структуру даних Python (наприклад `dict`) із значеннями та підзначеннями, які є сумісними з JSON.
+
+/// note | Примітка
+
+`jsonable_encoder` фактично використовується **FastAPI** внутрішньо для перетворення даних. Проте вона корисна в багатьох інших сценаріях.
+
+///
diff --git a/docs/uk/docs/tutorial/extra-data-types.md b/docs/uk/docs/tutorial/extra-data-types.md
new file mode 100644
index 000000000..5da942b6e
--- /dev/null
+++ b/docs/uk/docs/tutorial/extra-data-types.md
@@ -0,0 +1,62 @@
+# Додаткові типи даних
+
+До цього часу, ви використовували загальнопоширені типи даних, такі як:
+
+* `int`
+* `float`
+* `str`
+* `bool`
+
+Але можна також використовувати більш складні типи даних.
+
+І ви все ще матимете ті ж можливості, які були показані до цього:
+
+* Чудова підтримка редактора.
+* Конвертація даних з вхідних запитів.
+* Конвертація даних для відповіді.
+* Валідація даних.
+* Автоматична анотація та документація.
+
+## Інші типи даних
+
+Ось додаткові типи даних для використання:
+
+* `UUID`:
+ * Стандартний "Універсальний Унікальний Ідентифікатор", який часто використовується як ідентифікатор у багатьох базах даних та системах.
+ * У запитах та відповідях буде представлений як `str`.
+* `datetime.datetime`:
+ * Пайтонівський `datetime.datetime`.
+ * У запитах та відповідях буде представлений як `str` в форматі ISO 8601, як: `2008-09-15T15:53:00+05:00`.
+* `datetime.date`:
+ * Пайтонівський `datetime.date`.
+ * У запитах та відповідях буде представлений як `str` в форматі ISO 8601, як: `2008-09-15`.
+* `datetime.time`:
+ * Пайтонівський `datetime.time`.
+ * У запитах та відповідях буде представлений як `str` в форматі ISO 8601, як: `14:23:55.003`.
+* `datetime.timedelta`:
+ * Пайтонівський `datetime.timedelta`.
+ * У запитах та відповідях буде представлений як `float` загальної кількості секунд.
+ * Pydantic також дозволяє представляти це як "ISO 8601 time diff encoding",
більше інформації дивись у документації.
+* `frozenset`:
+ * У запитах і відповідях це буде оброблено так само, як і `set`:
+ * У запитах список буде зчитано, дублікати будуть видалені та він буде перетворений на `set`.
+ * У відповідях, `set` буде перетворений на `list`.
+ * Згенерована схема буде вказувати, що значення `set` є унікальними (з використанням JSON Schema's `uniqueItems`).
+* `bytes`:
+ * Стандартний Пайтонівський `bytes`.
+ * У запитах і відповідях це буде оброблено як `str`.
+ * Згенерована схема буде вказувати, що це `str` з "форматом" `binary`.
+* `Decimal`:
+ * Стандартний Пайтонівський `Decimal`.
+ * У запитах і відповідях це буде оброблено так само, як і `float`.
+* Ви можете перевірити всі дійсні типи даних Pydantic тут:
типи даних Pydantic.
+
+## Приклад
+
+Ось приклад *path operation* з параметрами, використовуючи деякі з вищезазначених типів.
+
+{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[1,3,12:16] *}
+
+Зверніть увагу, що параметри всередині функції мають свій звичайний тип даних, і ви можете, наприклад, виконувати звичайні маніпуляції з датами, такі як:
+
+{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[18:19] *}
diff --git a/docs/uk/docs/tutorial/first-steps.md b/docs/uk/docs/tutorial/first-steps.md
new file mode 100644
index 000000000..e910c4ccc
--- /dev/null
+++ b/docs/uk/docs/tutorial/first-steps.md
@@ -0,0 +1,328 @@
+# Перші кроки
+
+Найпростіший файл FastAPI може виглядати так:
+
+{* ../../docs_src/first_steps/tutorial001.py *}
+
+Скопіюйте це до файлу `main.py`.
+
+Запустіть сервер:
+
+
+
+```console
+$ fastapi dev main.py
+INFO Using path main.py
+INFO Resolved absolute path /home/user/code/awesomeapp/main.py
+INFO Searching for package file structure from directories with __init__.py files
+INFO Importing from /home/user/code/awesomeapp
+
+ ╭─ Python module file ─╮
+ │ │
+ │ 🐍 main.py │
+ │ │
+ ╰──────────────────────╯
+
+INFO Importing module main
+INFO Found importable FastAPI app
+
+ ╭─ Importable FastAPI app ─╮
+ │ │
+ │ from main import app │
+ │ │
+ ╰──────────────────────────╯
+
+INFO Using import string main:app
+
+ ╭────────── FastAPI CLI - Development mode ───────────╮
+ │ │
+ │ Serving at: http://127.0.0.1:8000 │
+ │ │
+ │ API docs: http://127.0.0.1:8000/docs │
+ │ │
+ │ Running in development mode, for production use: │
+ │ │
+ │ fastapi run │
+ │ │
+ ╰─────────────────────────────────────────────────────╯
+
+INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp']
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [2265862] using WatchFiles
+INFO: Started server process [2265873]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+У консолі буде рядок приблизно такого змісту:
+
+```hl_lines="4"
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+Цей рядок показує URL, за яким додаток запускається на вашій локальній машині.
+
+### Перевірте
+
+Відкрийте браузер та введіть адресу
http://127.0.0.1:8000.
+
+Ви побачите у відповідь таке повідомлення у форматі JSON:
+
+```JSON
+{"message": "Hello World"}
+```
+
+### Інтерактивна API документація
+
+Перейдемо сюди
http://127.0.0.1:8000/docs.
+
+Ви побачите автоматичну інтерактивну API документацію (створену завдяки
Swagger UI):
+
+
+
+### Альтернативна API документація
+
+Тепер перейдемо сюди
http://127.0.0.1:8000/redoc.
+
+Ви побачите альтернативну автоматичну документацію (створену завдяки
ReDoc):
+
+
+
+### OpenAPI
+
+**FastAPI** генерує "схему" з усім вашим API, використовуючи стандарт **OpenAPI** для визначення API.
+
+#### "Схема"
+
+"Схема" - це визначення або опис чогось. Це не код, який його реалізує, а просто абстрактний опис.
+
+#### API "схема"
+
+У цьому випадку,
OpenAPI є специфікацією, яка визначає, як описати схему вашого API.
+
+Це визначення схеми включає шляхи (paths) вашого API, можливі параметри, які вони приймають тощо.
+
+#### "Схема" даних
+
+Термін "схема" також може відноситися до структури даних, наприклад, JSON.
+
+У цьому випадку це означає - атрибути JSON і типи даних, які вони мають тощо.
+
+#### OpenAPI і JSON Schema
+
+OpenAPI описує схему для вашого API. І ця схема включає визначення (або "схеми") даних, що надсилаються та отримуються вашим API за допомогою **JSON Schema**, стандарту для схем даних JSON.
+
+#### Розглянемо `openapi.json`
+
+Якщо вас цікавить, як виглядає вихідна схема OpenAPI, то FastAPI автоматично генерує JSON-схему з усіма описами API.
+
+Ознайомитися можна за посиланням:
http://127.0.0.1:8000/openapi.json.
+
+Ви побачите приблизно такий JSON:
+
+```JSON
+{
+ "openapi": "3.1.0",
+ "info": {
+ "title": "FastAPI",
+ "version": "0.1.0"
+ },
+ "paths": {
+ "/items/": {
+ "get": {
+ "responses": {
+ "200": {
+ "description": "Successful Response",
+ "content": {
+ "application/json": {
+
+
+
+...
+```
+
+#### Для чого потрібний OpenAPI
+
+Схема OpenAPI є основою для обох систем інтерактивної документації.
+
+Існують десятки альтернативних інструментів, заснованих на OpenAPI. Ви можете легко додати будь-який з них до **FastAPI** додатку.
+
+Ви також можете використовувати OpenAPI для автоматичної генерації коду для клієнтів, які взаємодіють з API. Наприклад, для фронтенд-, мобільних або IoT-додатків
+
+## А тепер крок за кроком
+
+### Крок 1: імпортуємо `FastAPI`
+
+{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
+
+`FastAPI` це клас у Python, який надає всю функціональність для API.
+
+/// note | Технічні деталі
+
+`FastAPI` це клас, який успадковується безпосередньо від `Starlette`.
+
+Ви також можете використовувати всю функціональність
Starlette у `FastAPI`.
+
+///
+
+### Крок 2: створюємо екземпляр `FastAPI`
+
+{* ../../docs_src/first_steps/tutorial001.py hl[3] *}
+Змінна `app` є екземпляром класу `FastAPI`.
+
+Це буде головна точка для створення і взаємодії з API.
+
+### Крок 3: визначте операцію шляху (path operation)
+
+#### Шлях (path)
+
+"Шлях" це частина URL, яка йде одразу після символу `/`.
+
+Отже, у такому URL, як:
+
+```
+https://example.com/items/foo
+```
+
+...шлях буде:
+
+```
+/items/foo
+```
+
+/// info | Додаткова інформація
+
+"Шлях" (path) також зазвичай називають "ендпоінтом" (endpoint) або "маршрутом" (route).
+
+///
+
+При створенні API, "шлях" є основним способом розділення "завдань" і "ресурсів".
+#### Operation
+
+"Операція" (operation) тут означає один з "методів" HTTP.
+
+Один з:
+
+* `POST`
+* `GET`
+* `PUT`
+* `DELETE`
+
+...та більш екзотичних:
+
+* `OPTIONS`
+* `HEAD`
+* `PATCH`
+* `TRACE`
+
+У HTTP-протоколі можна спілкуватися з кожним шляхом, використовуючи один (або кілька) з цих "методів".
+
+---
+
+При створенні API зазвичай використовуються конкретні методи HTTP для виконання певних дій.
+
+Як правило, використовують:
+
+* `POST`: для створення даних.
+* `GET`: для читання даних.
+* `PUT`: для оновлення даних.
+* `DELETE`: для видалення даних.
+
+В OpenAPI кожен HTTP метод називається "операція".
+
+Ми також будемо дотримуватися цього терміна.
+
+#### Визначте декоратор операції шляху (path operation decorator)
+
+{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
+Декоратор `@app.get("/")` вказує **FastAPI**, що функція нижче, відповідає за обробку запитів, які надходять до неї:
+
+* шлях `/`
+* використовуючи
get
операцію
+
+/// info | `@decorator` Додаткова інформація
+
+Синтаксис `@something` у Python називається "декоратором".
+
+Ви розташовуєте його над функцією. Як гарний декоративний капелюх (мабуть, звідти походить термін).
+
+"Декоратор" приймає функцію нижче і виконує з нею якусь дію.
+
+У нашому випадку, цей декоратор повідомляє **FastAPI**, що функція нижче відповідає **шляху** `/` і **операції** `get`.
+
+Це і є "декоратор операції шляху (path operation decorator)".
+
+///
+
+Можна також використовувати операції:
+
+* `@app.post()`
+* `@app.put()`
+* `@app.delete()`
+
+І більш екзотичні:
+
+* `@app.options()`
+* `@app.head()`
+* `@app.patch()`
+* `@app.trace()`
+
+/// tip | Порада
+
+Ви можете використовувати кожну операцію (HTTP-метод) на свій розсуд.
+
+**FastAPI** не нав'язує жодного певного значення для кожного методу.
+
+Наведена тут інформація є рекомендацією, а не обов'язковою вимогою.
+
+Наприклад, під час використання GraphQL зазвичай усі дії виконуються тільки за допомогою `POST` операцій.
+
+///
+
+### Крок 4: визначте **функцію операції шляху (path operation function)**
+
+Ось "**функція операції шляху**":
+
+* **шлях**: це `/`.
+* **операція**: це `get`.
+* **функція**: це функція, яка знаходиться нижче "декоратора" (нижче `@app.get("/")`).
+
+{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
+
+Це звичайна функція Python.
+
+FastAPI викликатиме її щоразу, коли отримає запит до URL із шляхом "/", використовуючи операцію `GET`.
+
+У даному випадку це асинхронна функція.
+
+---
+
+Ви також можете визначити її як звичайну функцію замість `async def`:
+
+{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
+
+/// note | Примітка
+
+Якщо не знаєте в чому різниця, подивіться [Конкурентність: *"Поспішаєш?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
+
+///
+
+### Крок 5: поверніть результат
+
+{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
+
+Ви можете повернути `dict`, `list`, а також окремі значення `str`, `int`, ітд.
+
+Також можна повернути моделі Pydantic (про це ви дізнаєтесь пізніше).
+
+Існує багато інших об'єктів і моделей, які будуть автоматично конвертовані в JSON (зокрема ORM тощо). Спробуйте використати свої улюблені, велика ймовірність, що вони вже підтримуються.
+
+## Підіб'ємо підсумки
+
+* Імпортуємо `FastAPI`.
+* Створюємо екземпляр `app`.
+* Пишемо **декоратор операції шляху** як `@app.get("/")`.
+* Пишемо **функцію операції шляху**; наприклад, `def root(): ...`.
+* Запускаємо сервер у режимі розробки `fastapi dev`.
diff --git a/docs/uk/docs/tutorial/handling-errors.md b/docs/uk/docs/tutorial/handling-errors.md
new file mode 100644
index 000000000..12a356cd0
--- /dev/null
+++ b/docs/uk/docs/tutorial/handling-errors.md
@@ -0,0 +1,255 @@
+# Обробка Помилок
+
+Є багато ситуацій, коли потрібно повідомити клієнта, який використовує Ваш API, про помилку.
+
+Цим клієнтом може бути браузер із фронтендом, код іншого розробника, IoT-пристрій тощо.
+
+Можливо, Вам потрібно повідомити клієнта, що:
+
+* У нього недостатньо прав для виконання цієї операції.
+* Він не має доступу до цього ресурсу.
+* Елемент, до якого він намагається отримати доступ, не існує.
+* тощо.
+
+У таких випадках зазвичай повертається **HTTP статус-код** в діапазоні **400** (від 400 до 499).
+
+Це схоже на HTTP статус-коди 200 (від 200 до 299). Ці "200" статус-коди означають, що запит пройшов успішно.
+
+Статус-коди в діапазоні 400 означають, що сталася помилка з боку клієнта.
+
+Пам'ятаєте всі ці помилки **404 Not Found** (і жарти про них)?
+
+## Використання `HTTPException`
+
+Щоб повернути HTTP-відповіді з помилками клієнту, використовуйте `HTTPException`.
+
+### Імпорт `HTTPException`
+
+{* ../../docs_src/handling_errors/tutorial001.py hl[1] *}
+
+### Використання `HTTPException` у коді
+
+`HTTPException` — це звичайна помилка Python із додатковими даними, які стосуються API.
+
+Оскільки це помилка Python, Ви не `повертаєте` його, а `генеруєте` (генеруєте помилку).
+
+Це також означає, що якщо Ви перебуваєте всередині допоміжної функції, яку викликаєте всередині своєї *функції операції шляху*, і там генеруєте `HTTPException`, всередині цієї допоміжної функції, то решта коду в *функції операції шляху* не буде виконана. Запит одразу завершиться, і HTTP-помилка з `HTTPException` буде надіслана клієнту.
+
+Перевага використання `генерації` (raise) помилки замість `повернення` значення (return) стане більш очевидним в розділі про Залежності та Безпеку.
+
+У цьому прикладі, якщо клієнт запитує елемент за ID, якого не існує, буде згенеровано помилку зі статус-кодом `404`:
+
+{* ../../docs_src/handling_errors/tutorial001.py hl[11] *}
+
+### Отримана відповідь
+
+Якщо клієнт робить запит за шляхом `http://example.com/items/foo` (де `item_id` `"foo"`), він отримає статус-код 200 і JSON відповідь:
+
+```JSON
+{
+ "item": "The Foo Wrestlers"
+}
+```
+
+Але якщо клієнт робить запит на `http://example.com/items/bar` (де `item_id` має не існуюче значення `"bar"`), то отримає статус-код 404 (помилка "не знайдено") та відповідь:
+
+```JSON
+{
+ "detail": "Item not found"
+}
+```
+
+/// tip | Порада
+
+Під час виклику `HTTPException` Ви можете передати будь-яке значення, яке може бути перетворене в JSON, як параметр `detail`, а не лише рядок (`str`).
+
+Ви можете передати `dict`, `list` тощо.
+
+Вони обробляються автоматично за допомогою **FastAPI** та перетворюються в JSON.
+
+///
+
+## Додавання власних заголовків
+
+Іноді потрібно додати власні заголовки до HTTP-помилки, наприклад, для певних типів безпеки.
+
+Ймовірно, Вам не доведеться використовувати це безпосередньо у своєму коді.
+
+Але якщо Вам знадобиться це для складного сценарію, Ви можете додати власні заголовки:
+
+{* ../../docs_src/handling_errors/tutorial002.py hl[14] *}
+
+## Встановлення власних обробників помилок
+
+Ви можете додати власні обробники помилок за допомогою
тих самих утиліт обробки помилок зі Starlette.
+
+Припустимо, у Вас є власний обʼєкт помилки `UnicornException`, яке Ви (або бібліотека, яку Ви використовуєте) може `згенерувати` (`raise`).
+
+І Ви хочете обробляти це виключення глобально за допомогою FastAPI.
+
+Ви можете додати власний обробник виключень за допомогою `@app.exception_handler()`:
+
+{* ../../docs_src/handling_errors/tutorial003.py hl[5:7,13:18,24] *}
+
+Тут, якщо Ви звернетеся до `/unicorns/yolo`, то згенерується помилка `UnicornException`.
+
+Але вона буде оброблена функцією-обробником `unicorn_exception_handler`.
+
+Отже, Ви отримаєте зрозумілу помилку зі HTTP-статусом `418` і JSON-відповіддю:
+
+```JSON
+{"message": "Oops! yolo did something. There goes a rainbow..."}
+```
+
+/// note | Технічні деталі
+
+Ви також можете використовувати `from starlette.requests import Request` і `from starlette.responses import JSONResponse`.
+
+**FastAPI** надає ті самі `starlette.responses`, що й `fastapi.responses`, просто для зручності розробника. Але більшість доступних відповідей надходять безпосередньо зі Starlette. Те ж саме стосується і `Request`.
+
+///
+
+## Перевизначення обробників помилок за замовчуванням
+
+**FastAPI** має кілька обробників помилок за замовчуванням.
+
+Ці обробники відповідають за повернення стандартних JSON-відповідей, коли Ви `генеруєте` (`raise`) `HTTPException`, а також коли запит містить некоректні дані.
+
+Ви можете перевизначити ці обробники, створивши власні.
+
+### Перевизначення помилок валідації запиту
+
+Коли запит містить некоректні дані, **FastAPI** генерує `RequestValidationError`.
+
+І також включає обробник помилок за замовчуванням для нього.
+
+Щоб перевизначити його, імпортуйте `RequestValidationError` і використовуйте його з `@app.exception_handler(RequestValidationError)` для декорування обробника помилок.
+
+Обробник помилок отримує `Request` і саму помилку.
+
+{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:16] *}
+
+Тепер, якщо Ви перейдете за посиланням `/items/foo`, замість того, щоб отримати стандартну JSON-помилку:
+
+```JSON
+{
+ "detail": [
+ {
+ "loc": [
+ "path",
+ "item_id"
+ ],
+ "msg": "value is not a valid integer",
+ "type": "type_error.integer"
+ }
+ ]
+}
+```
+
+Ви отримаєте текстову версію:
+
+```
+1 validation error
+path -> item_id
+ value is not a valid integer (type=type_error.integer)
+```
+
+#### `RequestValidationError` проти `ValidationError`
+
+/// warning | Увага
+
+Це технічні деталі, які Ви можете пропустити, якщо вони зараз не важливі для Вас.
+
+///
+
+`RequestValidationError` є підкласом Pydantic
`ValidationError`.
+
+**FastAPI** використовує його для того, якщо Ви використовуєте модель Pydantic у `response_model` і у ваших даних є помилка, Ви побачили помилку у своєму журналі.
+
+Але клієнт/користувач не побачить її. Натомість клієнт отримає "Internal Server Error" зі статусом HTTP `500`.
+
+Так має бути, якщо у Вас виникла `ValidationError` Pydantic у *відповіді* або деінде у вашому коді (не у *запиті* клієнта), це насправді є помилкою у Вашому коді.
+
+І поки Ви її виправляєте, клієнти/користувачі не повинні мати доступу до внутрішньої інформації про помилку, оскільки це може призвести до вразливості безпеки.
+
+### Перевизначення обробника помилок `HTTPException`
+
+Аналогічно, Ви можете перевизначити обробник `HTTPException`.
+
+Наприклад, Ви можете захотіти повернути текстову відповідь замість JSON для цих помилок:
+
+{* ../../docs_src/handling_errors/tutorial004.py hl[3:4,9:11,22] *}
+
+/// note | Технічні деталі
+
+Ви також можете використовувати `from starlette.responses import PlainTextResponse`.
+
+**FastAPI** надає ті самі `starlette.responses`, що й `fastapi.responses`, просто для зручності розробника. Але більшість доступних відповідей надходять безпосередньо зі Starlette.
+
+///
+
+### Використання тіла `RequestValidationError`
+
+`RequestValidationError` містить `body`, який він отримав із некоректними даними.
+
+Ви можете використовувати це під час розробки свого додатка, щоб логувати тіло запиту та налагоджувати його, повертати користувачеві тощо.
+
+{* ../../docs_src/handling_errors/tutorial005.py hl[14] *}
+
+Тепер спробуйте надіслати некоректний елемент, наприклад:
+
+```JSON
+{
+ "title": "towel",
+ "size": "XL"
+}
+```
+Ви отримаєте відповідь, яка повідомить Вам, які саме дані є некоректні у вашому тілі запиту:
+
+
+```JSON hl_lines="12-15"
+{
+ "detail": [
+ {
+ "loc": [
+ "body",
+ "size"
+ ],
+ "msg": "value is not a valid integer",
+ "type": "type_error.integer"
+ }
+ ],
+ "body": {
+ "title": "towel",
+ "size": "XL"
+ }
+}
+```
+
+#### `HTTPException` FastAPI проти `HTTPException` Starlette
+
+**FastAPI** має власний `HTTPException`.
+
+І клас помилки `HTTPException` в **FastAPI** успадковується від класу помилки `HTTPException` в Starlette.
+
+Єдина різниця полягає в тому, що `HTTPException` в **FastAPI** приймає будь-які дані, які можна перетворити на JSON, для поля `detail`, тоді як `HTTPException` у Starlette приймає тільки рядки.
+
+Отже, Ви можете продовжувати використовувати `HTTPException` в **FastAPI** як зазвичай у своєму коді.
+
+Але коли Ви реєструєте обробник виключень, слід реєструвати його для `HTTPException` зі Starlette.
+
+Таким чином, якщо будь-яка частина внутрішнього коду Starlette або розширення чи плагін Starlette згенерує (raise) `HTTPException`, Ваш обробник зможе перехопити та обробити її.
+
+У цьому прикладі, щоб мати можливість використовувати обидва `HTTPException` в одному коді, помилка Starlette перейменовується на `StarletteHTTPException`:
+
+```Python
+from starlette.exceptions import HTTPException as StarletteHTTPException
+```
+
+### Повторне використання обробників помилок **FastAPI**
+
+Якщо Ви хочете використовувати помилки разом із такими ж обробниками помилок за замовчуванням, як у **FastAPI**, Ви можете імпортувати та повторно використовувати їх із `fastapi.exception_handlers`:
+
+{* ../../docs_src/handling_errors/tutorial006.py hl[2:5,15,21] *}
+
+У цьому прикладі Ви просто використовуєте `print` для виведення дуже інформативного повідомлення, але Ви зрозуміли основну ідею. Ви можете обробити помилку та повторно використовувати обробники помилок за замовчуванням.
diff --git a/docs/uk/docs/tutorial/header-param-models.md b/docs/uk/docs/tutorial/header-param-models.md
new file mode 100644
index 000000000..6f7b0bdae
--- /dev/null
+++ b/docs/uk/docs/tutorial/header-param-models.md
@@ -0,0 +1,58 @@
+# Моделі Параметрів Заголовків
+
+Якщо у Вас є група пов’язаних параметрів заголовків, Ви можете створити **Pydantic модель** для їх оголошення.
+
+Це дозволить Вам повторно **використовувати модель** в **різних місцях**, а також оголосити валідації та метадані для всіх параметрів одночасно. 😎
+
+/// note | Нотатки
+
+Ця можливість підтримується починаючи з версії FastAPI `0.115.0`. 🤓
+
+///
+
+## Параметри Заголовків з Використанням Pydantic Model
+
+Оголосіть потрібні **параметри заголовків** у **Pydantic моделі**, а потім оголосіть параметр як `Header`:
+
+{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *}
+
+FastAPI буде витягувати дані для кожного поля з заголовків у запиті та передавати їх у створену Вами Pydantic модель.
+
+**FastAPI** буде **витягувати** дані для **кожного поля** з **заголовків** у запиті та передавати їх у створену Вами Pydantic модель.
+
+## Перевірка в Документації
+
+Ви можете побачити необхідні заголовки в інтерфейсі документації за адресою `/docs`:
+
+
+

+
+
+## Заборона Додаткових Заголовків
+
+У деяких особливих випадках (ймовірно, не дуже поширених) Ви можете захотіти **обмежити** заголовки, які хочете отримати.
+
+Ви можете використати конфігурацію моделі Pydantic, щоб `заборонити` будь-які `додаткові` поля:
+
+{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *}
+
+Якщо клієнт спробує надіслати **додаткові заголовки**, він отримає **помилку** у відповіді.
+
+Наприклад, якщо клієнт спробує надіслати заголовок `tool` зі значенням `plumbus`, він отримає **помилку** з повідомленням про те, що параметр заголовка `tool` не дозволений:
+
+```json
+{
+ "detail": [
+ {
+ "type": "extra_forbidden",
+ "loc": ["header", "tool"],
+ "msg": "Extra inputs are not permitted",
+ "input": "plumbus",
+ }
+ ]
+}
+```
+
+## Підсумок
+
+Ви можете використовувати **Pydantic моделі** для оголошення **заголовків** у **FastAPI**. 😎
diff --git a/docs/uk/docs/tutorial/header-params.md b/docs/uk/docs/tutorial/header-params.md
new file mode 100644
index 000000000..09c70a4f6
--- /dev/null
+++ b/docs/uk/docs/tutorial/header-params.md
@@ -0,0 +1,91 @@
+# Header-параметри
+
+Ви можете визначати параметри заголовків, так само як визначаєте `Query`, `Path` і `Cookie` параметри.
+
+## Імпорт `Header`
+
+Спочатку імпортуйте `Header`:
+
+{* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *}
+
+## Оголошення параметрів `Header`
+
+Потім оголосіть параметри заголовків, використовуючи ту ж структуру, що й для `Path`, `Query` та `Cookie`.
+
+Ви можете визначити значення за замовчуванням, а також усі додаткові параметри валідації або анотації:
+
+{* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *}
+
+/// note | Технічні деталі
+
+`Header`є "сестринським" класом для `Path`, `Query` і `Cookie`. Він також успадковується від загального класу `Param`.
+
+Але пам’ятайте, що при імпорті `Query`, `Path`, `Header` та інших із `fastapi`, то насправді вони є функціями, які повертають спеціальні класи.
+
+///
+
+/// info | Інформація
+
+Щоб оголосити заголовки, потрібно використовувати `Header`, інакше параметри будуть інтерпретуватися як параметри запиту.
+
+///
+
+## Автоматичне перетворення
+
+`Header` має додатковий функціонал порівняно з `Path`, `Query` та `Cookie`.
+
+Більшість стандартних заголовків розділяються символом «дефіс», також відомим як «мінус» (`-`).
+
+Але змінна, така як `user-agent`, є недійсною в Python.
+
+Тому, за замовчуванням, `Header` автоматично перетворює символи підкреслення (`_`) на дефіси (`-`) для отримання та документування заголовків.
+
+Оскільки заголовки HTTP не чутливі до регістру, Ви можете використовувати стандартний стиль Python ("snake_case").
+
+Тому Ви можете використовувати `user_agent`, як зазвичай у коді Python, замість того щоб писати з великої літери, як `User_Agent` або щось подібне.
+
+Якщо Вам потрібно вимкнути автоматичне перетворення підкреслень у дефіси, встановіть `convert_underscores` в `Header` значення `False`:
+
+{* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *}
+
+/// warning | Увага
+
+Перед тим як встановити значення `False` для `convert_underscores` пам’ятайте, що деякі HTTP-проксі та сервери не підтримують заголовки з підкресленнями.
+
+///
+
+## Дубльовані заголовки
+
+Можливо отримати дубльовані заголовки, тобто той самий заголовок із кількома значеннями.
+
+Це можна визначити, використовуючи список у типізації параметра.
+
+Ви отримаєте всі значення дубльованого заголовка у вигляді `list` у Python.
+
+Наприклад, щоб оголосити заголовок `X-Token`, який може з’являтися більше ніж один раз:
+
+{* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *}
+
+Якщо Ви взаємодієте з цією операцією шляху, надсилаючи два HTTP-заголовки, наприклад:
+
+```
+X-Token: foo
+X-Token: bar
+```
+
+Відповідь буде така:
+
+```JSON
+{
+ "X-Token values": [
+ "bar",
+ "foo"
+ ]
+}
+```
+
+## Підсумок
+
+Оголошуйте заголовки за допомогою `Header`, використовуючи той самий підхід, що й для `Query`, `Path` та `Cookie`.
+
+Не хвилюйтеся про підкреслення у змінних — **FastAPI** автоматично конвертує їх.
diff --git a/docs/uk/docs/tutorial/index.md b/docs/uk/docs/tutorial/index.md
new file mode 100644
index 000000000..92c3e77a3
--- /dev/null
+++ b/docs/uk/docs/tutorial/index.md
@@ -0,0 +1,83 @@
+# Туторіал - Посібник користувача
+
+У цьому посібнику показано, як користуватися **FastAPI** з більшістю його функцій, крок за кроком.
+
+Кожен розділ поступово надбудовується на попередні, але він структурований на окремі теми, щоб ви могли перейти безпосередньо до будь-якої конкретної, щоб вирішити ваші конкретні потреби API.
+
+Він також створений як довідник для роботи у майбутньому.
+
+Тож ви можете повернутися і побачити саме те, що вам потрібно.
+
+## Запустіть код
+
+Усі блоки коду можна скопіювати та використовувати безпосередньо (це фактично перевірені файли Python).
+
+Щоб запустити будь-який із прикладів, скопіюйте код у файл `main.py` і запустіть `uvicorn` за допомогою:
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [28720]
+INFO: Started server process [28722]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+**ДУЖЕ радимо** написати або скопіювати код, відредагувати його та запустити локально.
+
+Використання його у своєму редакторі – це те, що дійсно показує вам переваги FastAPI, бачите, як мало коду вам потрібно написати, всі перевірки типів, автозаповнення тощо.
+
+---
+
+## Встановлення FastAPI
+
+Першим кроком є встановлення FastAPI.
+
+Для туторіалу ви можете встановити його з усіма необов’язковими залежностями та функціями:
+
+
+
+```console
+$ pip install "fastapi[all]"
+
+---> 100%
+```
+
+
+
+...який також включає `uvicorn`, який ви можете використовувати як сервер, який запускає ваш код.
+
+/// note
+
+Ви також можете встановити його частина за частиною.
+
+Це те, що ви, ймовірно, зробили б, коли захочете розгорнути свою програму у виробничому середовищі:
+
+```
+pip install fastapi
+```
+
+Також встановіть `uvicorn`, щоб він працював як сервер:
+
+```
+pip install "uvicorn[standard]"
+```
+
+І те саме для кожної з опціональних залежностей, які ви хочете використовувати.
+
+///
+
+## Розширений посібник користувача
+
+Існує також **Розширений посібник користувача**, який ви зможете прочитати пізніше після цього **Туторіал - Посібник користувача**.
+
+**Розширений посібник користувача** засновано на цьому, використовує ті самі концепції та навчає вас деяким додатковим функціям.
+
+Але вам слід спочатку прочитати **Туторіал - Посібник користувача** (те, що ви зараз читаєте).
+
+Він розроблений таким чином, що ви можете створити повну програму лише за допомогою **Туторіал - Посібник користувача**, а потім розширити її різними способами, залежно від ваших потреб, використовуючи деякі з додаткових ідей з **Розширеного посібника користувача** .
diff --git a/docs/uk/docs/tutorial/metadata.md b/docs/uk/docs/tutorial/metadata.md
new file mode 100644
index 000000000..64e667ec6
--- /dev/null
+++ b/docs/uk/docs/tutorial/metadata.md
@@ -0,0 +1,120 @@
+# Метадані та URL-адреси документації
+
+Ви можете налаштувати кілька конфігурацій метаданих у Вашому додатку **FastAPI**.
+
+## Метадані для API
+
+Ви можете встановити такі поля, які використовуються в специфікації OpenAPI та в автоматично згенерованих інтерфейсах документації API:
+
+| Параметр | Тип | Опис |
+|------------|------|-------------|
+| `title` | `str` | Назва API. |
+| `summary` | `str` | Короткий опис API.
Доступно з OpenAPI 3.1.0, FastAPI 0.99.0. |
+| `description` | `str` | Більш детальний опис API. Може використовувати Markdown. |
+| `version` | `string` | Версія API. Це версія Вашого додатка, а не OpenAPI. Наприклад, `2.5.0`. |
+| `terms_of_service` | `str` | URL до умов використання API. Якщо вказано, має бути у форматі URL. |
+| `contact` | `dict` | Інформація для контакту з API. Може містити кілька полів.
contact
поля
Параметр | Тип | Опис |
---|
name | str | Ім'я контактної особи або організації. |
url | str | URL з інформацією для контакту. Повинен бути у форматі URL. |
email | str | Email контактної особи або організації. Повинен бути у форматі електронної пошти. |
|
+| `license_info` | `dict` | Інформація про ліцензію для API. Може містити кілька полів.
license_info
поля
Параметр | Тип | Опис |
---|
name | str | ОБОВ'ЯЗКОВО (якщо встановлено license_info ). Назва ліцензії для API. |
identifier | str | Ліцензійний вираз за SPDX для API. Поле identifier взаємовиключне з полем url . Доступно з OpenAPI 3.1.0, FastAPI 0.99.0. |
url | str | URL до ліцензії, яка використовується для API. Повинен бути у форматі URL. |
|
+
+Ви можете налаштувати їх наступним чином:
+
+{* ../../docs_src/metadata/tutorial001.py hl[3:16, 19:32] *}
+
+/// tip | Підказка
+
+У полі `description` можна використовувати Markdown, і він буде відображатися у результаті.
+
+///
+
+З цією конфігурацією автоматична документація API виглядатиме так:
+
+

+
+## Ідентифікатор ліцензії
+
+З початку використання OpenAPI 3.1.0 та FastAPI 0.99.0 Ви також можете налаштувати `license_info` за допомогою `identifier` замість `url`.
+
+Наприклад:
+
+{* ../../docs_src/metadata/tutorial001_1.py hl[31] *}
+
+## Метадані для тегів
+
+Ви також можете додати додаткові метадані для різних тегів, які використовуються для групування операцій шляхів, за допомогою параметра `openapi_tags`.
+
+Він приймає список, який містить один словник для кожного тега.
+
+Кожен словник може містити:
+
+* `name` (**обов'язково**): `str` з тією ж назвою тегу, яку Ви використовуєте у параметрі `tags` у Ваших *операціях шляху* та `APIRouter`s.
+* `description`: `str` з коротким описом тегу. Може містити Markdown і буде відображено в інтерфейсі документації.
+* `externalDocs`: `dict` який описує зовнішню документацію з такими полями:
+ * `description`: `str` з коротким описом зовнішньої документації.
+ * `url` (**обов'язково**): `str`з URL-адресою зовнішньої документації.
+
+### Створення метаданих для тегів
+
+Спробуймо це на прикладі з тегами для `users` та `items`.
+
+Створіть метадані для своїх тегів і передайте їх у параметр `openapi_tags`:
+
+{* ../../docs_src/metadata/tutorial004.py hl[3:16,18] *}
+
+Зверніть увагу, що в описах можна використовувати Markdown, наприклад, "login" буде показано жирним шрифтом (**login**), а "fancy" буде показано курсивом (_fancy_).
+
+/// tip | Порада
+
+Не обов'язково додавати метадані для всіх тегів, які Ви використовуєте.
+
+///
+
+### Використання тегів
+
+Використовуйте параметр `tags` зі своїми *операціями шляху* (і `APIRouter`) для призначення їх до різних тегів:
+
+{* ../../docs_src/metadata/tutorial004.py hl[21,26] *}
+
+/// info | Інформація
+
+Детальніше про теги читайте в розділі [Конфігурація шляхів операцій](path-operation-configuration.md#tags){.internal-link target=_blank}.
+
+///
+
+### Перевірка документації
+
+Якщо Ви зараз перевірите документацію, вона покаже всі додаткові метадані:
+
+

+
+### Порядок тегів
+
+Порядок кожного словника метаданих тегу також визначає порядок відображення в інтерфейсі документації.
+
+Наприклад, хоча `users` мав би йти після `items` в алфавітному порядку, він відображається перед ними, оскільки ми додали його метадані як перший словник у списку.
+
+## URL для OpenAPI
+
+За замовчуванням схема OpenAPI надається за адресою `/openapi.json`.
+
+Але Ви можете налаштувати це за допомогою параметра `openapi_url`.
+
+Наприклад, щоб налаштувати його на `/api/v1/openapi.json`:
+
+{* ../../docs_src/metadata/tutorial002.py hl[3] *}
+
+Якщо Ви хочете повністю вимкнути схему OpenAPI, Ви можете встановити `openapi_url=None`, це також вимкне інтерфейси документації, які її використовують.
+
+## URL-адреси документації
+
+Ви можете налаштувати два інтерфейси користувача для документації, які включені:
+
+* **Swagger UI**: доступний за адресою `/docs`.
+ * Ви можете змінити його URL за допомогою параметра `docs_url`.
+ * Ви можете вимкнути його, встановивши `docs_url=None`.
+* **ReDoc**: доступний за адресою `/redoc`.
+ * Ви можете змінити його URL за допомогою параметра `redoc_url`.
+ * Ви можете вимкнути його, встановивши `redoc_url=None`.
+
+Наприклад, щоб налаштувати Swagger UI на `/documentation` і вимкнути ReDoc:
+
+{* ../../docs_src/metadata/tutorial003.py hl[3] *}
diff --git a/docs/uk/docs/tutorial/middleware.md b/docs/uk/docs/tutorial/middleware.md
new file mode 100644
index 000000000..807be484a
--- /dev/null
+++ b/docs/uk/docs/tutorial/middleware.md
@@ -0,0 +1,75 @@
+# Middleware (Проміжний шар)
+
+У **FastAPI** можна додавати middleware (проміжний шар).
+
+"Middleware" — це функція, яка працює з кожним **запитом** перед його обробкою будь-якою конкретною *операцією шляху* (*path operation*), а також з кожною **відповіддю** перед її поверненням.
+
+* Middleware отримує кожен **запит**, що надходить до Вашого застосунку.
+* Може виконати певні дії із цим **запитом** або запустити необхідний код.
+* Далі передає **запит** для обробки основним застосунком (*операцією шляху*).
+* Отримує **відповідь**, сформовану застосунком (*операцією шляху*).
+* Може змінити цю **відповідь** або виконати додатковий код.
+* Повертає **відповідь** клієнту.
+
+/// note | Технічні деталі
+
+Якщо у Вас є залежності з `yield`, код виходу виконається *після* middleware.
+
+Якщо були заплановані фонові задачі (background tasks - розглянуто далі), вони виконаються *після* всіх middleware.
+
+///
+
+## Створення middleware
+
+Щоб створити middleware, Ви використовуєте декоратор `@app.middleware("http")` на функції.
+
+Функція middleware отримує:
+
+* `Запит`.
+* Функцію `call_next`, яка приймає `запит` як параметр.
+ * Ця функція передає `запит` відповідній *операції шляху*.
+ * Потім вона повертає `відповідь`, згенеровану цією *операцією шляху*.
+
+* Ви можете ще змінити `відповідь` перед тим, як повернути її.
+
+
+{* ../../docs_src/middleware/tutorial001.py hl[8:9,11,14] *}
+
+/// tip | Порада
+
+Не забувайте, що власні заголовки можна додавати, використовуючи
префікс 'X-'.
+
+Але якщо у Вас є власні заголовки, які Ви хочете, щоб браузерний клієнт міг побачити, потрібно додати їх до Вашої конфігурації CORS (див. [CORS (Обмін ресурсами між різними джерелами)](cors.md){.internal-link target=_blank} за допомогою параметра `expose_headers`, описаного в
документації Starlette по CORS.
+
+///
+
+/// note | Технічні деталі
+
+Ви також можете використати `from starlette.requests import Request`.
+
+**FastAPI** надає це для Вашої зручності як розробника. Але він походить безпосередньо зі Starlette.
+
+///
+
+### До і після `response`(`відповіді`)
+
+Ви можете додати код, який буде виконуватися з `запитом` (`request`), до того, як його обробить будь-яка *операція шляху* (*path operation*).
+
+Також Ви можете додати код, який буде виконуватися після того, як `відповідь` (`response`) буде згенеровано, перед тим як його повернути.
+
+Наприклад, Ви можете додати власний заголовок `X-Process-Time`, який міститиме час у секундах, який витратився на обробку запиту та генерацію відповіді:
+
+{* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *}
+
+
+/// tip | Підказка
+
+Тут ми використовуємо
`time.perf_counter()` замість `time.time()` оскільки він може бути більш точним для таких випадків. 🤓
+
+///
+
+## Інші middlewares
+
+Ви можете пізніше прочитати більше про інші middlewares в [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}.
+
+Ви дізнаєтесь, як обробляти
CORS за допомогою middleware в наступному розділі.
diff --git a/docs/uk/docs/tutorial/path-params-numeric-validations.md b/docs/uk/docs/tutorial/path-params-numeric-validations.md
new file mode 100644
index 000000000..281ee183c
--- /dev/null
+++ b/docs/uk/docs/tutorial/path-params-numeric-validations.md
@@ -0,0 +1,165 @@
+# Path Параметри та валідація числових даних
+
+Так само як Ви можете оголошувати додаткові перевірки та метадані для query параметрів за допомогою `Query`, Ви можете оголошувати той самий тип перевірок і метаданих для параметрів шляху за допомогою `Path`.
+
+## Імпорт Path
+
+Спочатку імпортуйте `Path` з `fastapi` і імпортуйте `Annotated`:
+
+{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *}
+
+/// info | Інформація
+
+FastAPI додав підтримку `Annotated` (і почав рекомендувати його використання) у версії 0.95.0.
+
+Якщо у Вас стара версія, при спробі використати `Annotated` можуть виникати помилки.
+
+Переконайтеся, що Ви [оновили версію FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} принаймні до версії 0.95.1 перед використанням `Annotated`.
+
+///
+
+## Оголошення метаданих
+
+Ви можете оголошувати всі ті ж параметри, що і для `Query`.
+
+Наприклад, щоб оголосити значення метаданих `title` для параметра шляху `item_id`, Ви можете написати:
+
+{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *}
+
+/// note | Примітка
+
+Параметр шляху завжди є обов’язковим, оскільки він має бути частиною шляху. Навіть якщо Ви оголосите його зі значенням `None` або встановите значення за замовчуванням — він все одно залишатиметься обов’язковим.
+
+///
+
+## Упорядковуйте параметри, як Вам потрібно
+
+/// tip | Підказка
+
+Це, мабуть, не настільки важливо або необхідно, якщо Ви використовуєте `Annotated`.
+
+///
+
+Припустимо, Ви хочете оголосити параметр запиту `q` як обов’язковий `str`.
+
+І Вам не потрібно оголошувати нічого іншого для цього параметра, тому немає потреби використовувати `Query`.
+
+Але Вам все одно потрібно використовувати `Path` для параметра шляху `item_id`. І з певних причин Ви не хочете використовувати `Annotated`.
+
+Python видасть помилку, якщо розмістити значення з "default" перед значенням, яке не має "default".
+
+Але Ви можете змінити порядок і розмістити значення без значення за замовчуванням (параметр запиту `q`) першим.
+
+
+Для **FastAPI** порядок не має значення. Він визначає параметри за їх іменами, типами та значеннями за замовчуванням (`Query`, `Path` тощо) і не звертає уваги на порядок.
+
+Тому Ви можете оголосити Вашу функцію так:
+
+//// tab | Python 3.8 non-Annotated
+
+/// tip | Підказка
+
+За можливості віддавайте перевагу версії з використанням `Annotated`.
+
+///
+
+{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *}
+
+////
+
+Але майте на увазі, що якщо Ви використовуєте `Annotated`, ця проблема не виникне, оскільки Ви не використовуєте значення за замовчуванням для параметрів `Query()` або `Path()`.
+
+{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *}
+
+## Упорядковуйте параметри за потребою, хитрощі
+
+/// tip | Підказка
+
+Це, мабуть, не настільки важливо або необхідно, якщо Ви використовуєте `Annotated`.
+
+///
+
+Ось **невелика хитрість**, яка може стати в пригоді, хоча вона рідко знадобиться.
+
+Якщо Ви хочете:
+
+* оголосити параметр запиту `q` без використання `Query` або значення за замовчуванням
+* оголосити параметр шляху `item_id`, використовуючи `Path`
+* розмістити їх у різному порядку
+* не використовувати `Annotated`
+
+...у Python є спеціальний синтаксис для цього.
+
+Передайте `*` як перший параметр функції.
+
+Python нічого не зробить із цією `*`, але розпізнає, що всі наступні параметри слід викликати як аргументи за ключовим словом (пари ключ-значення), також відомі як
kwargs
. Навіть якщо вони не мають значення за замовчуванням.
+
+{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *}
+
+### Краще з `Annotated`
+
+Майте на увазі, якщо Ви використовуєте `Annotated`, оскільки Ви не використовуєте значення за замовчуванням для параметрів функції, цієї проблеми не виникне, і, швидше за все, Вам не потрібно буде використовувати `*`.
+
+{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *}
+
+## Валідація числових даних: більше або дорівнює
+
+За допомогою `Query` і `Path` (та інших, які Ви побачите пізніше) можна оголошувати числові обмеження.
+
+Тут, завдяки `ge=1`, `item_id` має бути цілим числом, яке "`g`reater than or `e`qual" (більше або дорівнює) `1`.
+
+{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *}
+
+## Валідація числових даних: більше ніж і менше або дорівнює
+
+Те саме застосовується до:
+
+* `gt`: `g`reater `t`han (більше ніж)
+* `le`: `l`ess than or `e`qual (менше або дорівнює)
+
+{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *}
+
+## Валідація числових даних: float, більше ніж і менше ніж
+
+Валідація чисел також працює для значень типу `float`.
+
+Ось де стає важливо мати можливість оголошувати
gt
, а не тільки
ge
. Це дозволяє, наприклад, вимагати, щоб значення було більше `0`, навіть якщо воно менше `1`.
+
+Таким чином, значення `0.5` буде допустимим. Але `0.0` або `0` — ні.
+
+Те саме стосується
lt
.
+
+{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *}
+
+## Підсумок
+
+За допомогою `Query`, `Path` (і інших параметрів, які Ви ще не бачили) можна оголошувати метадані та перевірки рядків, так само як у [Query параметри та валідація рядків](query-params-str-validations.md){.internal-link target=_blank}.
+
+Також можна оголошувати числові перевірки:
+
+* `gt`: `g`reater `t`han (більше ніж)
+* `ge`: `g`reater than or `e`qual (більше або дорівнює)
+* `lt`: `l`ess `t`han (менше ніж)
+* `le`: `l`ess than or `e`qual (менше або дорівнює)
+
+/// info | Інформація
+
+`Query`, `Path` та інші класи, які Ви побачите пізніше, є підкласами спільного класу `Param`.
+
+Всі вони мають однакові параметри для додаткових перевірок і метаданих, які Ви вже бачили.
+
+///
+
+/// note | Технічні деталі
+
+Коли Ви імпортуєте `Query`, `Path` та інші з `fastapi`, насправді це функції.
+
+При виклику вони повертають екземпляри класів з такими ж іменами.
+
+Тобто Ви імпортуєте `Query`, яка є функцією. А коли Ви її викликаєте, вона повертає екземпляр класу, який теж називається `Query`.
+
+Ці функції створені таким чином (замість використання класів напряму), щоб Ваш редактор не відзначав їхні типи як помилки.
+
+Таким чином, Ви можете користуватися своїм звичайним редактором і інструментами для програмування без додаткових налаштувань для ігнорування таких помилок.
+
+///
diff --git a/docs/uk/docs/tutorial/path-params.md b/docs/uk/docs/tutorial/path-params.md
new file mode 100644
index 000000000..e7df1f19a
--- /dev/null
+++ b/docs/uk/docs/tutorial/path-params.md
@@ -0,0 +1,261 @@
+# Path Параметри
+
+Ви можете визначити "параметри" або "змінні" шляху, використовуючи синтаксис форматованих рядків:
+
+{* ../../docs_src/path_params/tutorial001.py hl[6:7] *}
+
+Значення параметра шляху `item_id` передається у функцію як аргумент `item_id`.
+
+Якщо запустити цей приклад та перейти за посиланням
http://127.0.0.1:8000/items/foo, то отримаємо таку відповідь:
+
+```JSON
+{"item_id":"foo"}
+```
+
+## Path параметри з типами
+
+Ви можете визначити тип параметра шляху у функції, використовуючи стандартні анотації типів Python:
+
+{* ../../docs_src/path_params/tutorial002.py hl[7] *}
+
+У такому випадку `item_id` визначається як `int`.
+
+/// check | Примітка
+
+Це дасть можливість підтримки редактора всередині функції з перевірками помилок, автодоповнення тощо.
+
+///
+
+##
Перетворення даних
+
+Якщо запустити цей приклад і перейти за посиланням
http://127.0.0.1:8000/items/3, то отримаєте таку відповідь:
+
+```JSON
+{"item_id":3}
+```
+
+/// check | Примітка
+
+Зверніть увагу, що значення, яке отримала (і повернула) ваша функція, — це `3`. Це Python `int`, а не рядок `"3"`.
+
+Отже, з таким оголошенням типу **FastAPI** автоматично виконує
"парсинг" запитів.
+
+///
+
+##
Перевірка даних
+
+Якщо ж відкрити у браузері посилання
http://127.0.0.1:8000/items/foo, то побачимо цікаву HTTP-помилку:
+
+```JSON
+{
+ "detail": [
+ {
+ "type": "int_parsing",
+ "loc": [
+ "path",
+ "item_id"
+ ],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "foo",
+ "url": "https://errors.pydantic.dev/2.1/v/int_parsing"
+ }
+ ]
+}
+```
+тому що параметр шляху має значення `"foo"`, яке не є типом `int`.
+
+Таку саму помилку отримаємо, якщо передати `float` замість `int`, як бачимо, у цьому прикладі:
http://127.0.0.1:8000/items/4.2
+
+/// check | Примітка
+
+Отже, **FastAPI** надає перевірку типів з таким самим оголошенням типу в Python.
+
+Зверніть увагу, що помилка також чітко вказує саме на те місце, де валідація не пройшла.
+
+Це неймовірно корисно під час розробки та дебагінгу коду, що взаємодіє з вашим API.
+
+///
+
+## Документація
+
+Тепер коли відкриєте свій браузер за посиланням
http://127.0.0.1:8000/docs, то побачите автоматично згенеровану, інтерактивну API-документацію:
+
+

+
+/// check | Примітка
+
+Знову ж таки, лише з цим самим оголошенням типу в Python, FastAPI надає вам автоматичну, інтерактивну документацію (з інтеграцією Swagger UI).
+
+Зверніть увагу, що параметр шляху оголошений як ціле число.
+
+
+///
+
+## Переваги стандартизації, альтернативна документація
+
+І оскільки згенерована схема відповідає стандарту
OpenAPI, існує багато сумісних інструментів.
+
+З цієї причини FastAPI також надає альтернативну документацію API (використовуючи ReDoc), до якої можна отримати доступ за посиланням
http://127.0.0.1:8000/redoc:
+
+

+
+Таким чином, існує багато сумісних інструментів, включаючи інструменти для генерації коду для багатьох мов.
+
+
+## Pydantic
+
+Вся валідація даних виконується за лаштунками за допомогою
Pydantic, тому Ви отримуєте всі переваги від його використання. І можете бути впевнені, що все в надійних руках.
+
+Ви можете використовувати ті самі оголошення типів з `str`, `float`, `bool` та багатьма іншими складними типами даних.
+
+Декілька з них будуть розглянуті в наступних розділах посібника.
+
+## Порядок має значення
+
+При створенні *операцій шляху* можуть виникати ситуації, коли шлях фіксований.
+
+Наприклад, `/users/me`. Припустимо, що це шлях для отримання даних про поточного користувача.
+
+А також у вас може бути шлях `/users/{user_id}`, щоб отримати дані про конкретного користувача за його ID.
+
+Оскільки *операції шляху* оцінюються по черзі, Ви повинні переконатися, що шлях для `/users/me` оголошений перед шляхом для `/users/{user_id}`:
+
+{* ../../docs_src/path_params/tutorial003.py hl[6,11] *}
+
+Інакше шлях для `/users/{user_id}` також буде відповідати для `/users/me`, "вважаючи", що він отримує параметр `user_id` зі значенням `"me"`.
+
+Аналогічно, Ви не можете оголосити операцію шляху:
+
+{* ../../docs_src/path_params/tutorial003b.py hl[6,11] *}
+
+Перша операція буде завжди використовуватися, оскільки шлях збігається першим.
+## Попередньо визначені значення
+
+Якщо у вас є *операція шляху*, яка приймає *параметр шляху*, але Ви хочете, щоб можливі допустимі значення *параметра шляху* були попередньо визначені, Ви можете використати стандартний Python
Enum.
+
+### Створення класу `Enum`
+
+Імпортуйте `Enum` і створіть підклас, що наслідується від `str` та `Enum`.
+
+Наслідуючи від `str`, документація API зможе визначити, що значення повинні бути типу `string`, і правильно їх відобразить.
+
+Після цього створіть атрибути класу з фіксованими значеннями, які будуть доступними допустимими значеннями:
+
+{* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *}
+
+/// info | Додаткова інформація
+
+
Перелічення (або enums) доступні в Python починаючи з версії 3.4.
+
+///
+
+/// tip | Порада
+
+Якщо вам цікаво, "AlexNet", "ResNet" та "LeNet" — це просто назви ML моделей
Machine Learning.
+
+///
+
+
+### Оголосіть *параметр шляху*
+
+Потім створіть *параметр шляху* з анотацією типу, використовуючи створений вами клас enum (`ModelName`):
+
+{* ../../docs_src/path_params/tutorial005.py hl[16] *}
+
+### Перевірка документації
+
+Оскільки доступні значення для *параметра шляху* визначені заздалегідь, інтерактивна документація зможе красиво їх відобразити:
+
+

+
+### Робота з *перелічуваннями* у Python
+
+Значення *параметра шляху* буде елементом *перелічування*.
+
+#### Порівняння *елементів перелічування*
+
+Ви можете порівнювати його з *елементами перелічування* у створеному вами enum `ModelName`:
+
+{* ../../docs_src/path_params/tutorial005.py hl[17] *}
+
+#### Отримання *значення перелічування*
+
+Ви можете отримати фактичне значення (у цьому випадку це `str`), використовуючи `model_name.value`, або загалом `your_enum_member.value`:
+
+{* ../../docs_src/path_params/tutorial005.py hl[20] *}
+
+/// tip | Порада
+
+Ви також можете отримати доступ до значення `"lenet"`, використовуючи `ModelName.lenet.value`.
+
+///
+
+
+#### Повернення *елементів перелічування*
+
+Ви можете повертати *елементи перелічування* з вашої *операції шляху*, навіть вкладені у JSON-тіло (наприклад, `dict`).
+
+Вони будуть перетворені на відповідні значення (у цьому випадку рядки) перед поверненням клієнту:
+
+{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *}
+
+На стороні клієнта Ви отримаєте відповідь у форматі JSON, наприклад:
+
+```JSON
+{
+ "model_name": "alexnet",
+ "message": "Deep Learning FTW!"
+}
+```
+
+## Path-параметри, що містять шляхи
+
+Припустимо, у вас є *операція шляху* з маршрутом `/files/{file_path}`.
+
+Але вам потрібно, щоб `file_path` містив *шлях*, наприклад `home/johndoe/myfile.txt`.
+
+Отже, URL для цього файлу виглядатиме так: `/files/home/johndoe/myfile.txt`.
+
+
+
+### Підтримка OpenAPI
+
+OpenAPI не підтримує спосіб оголошення *параметра шляху*, що містить *шлях* всередині, оскільки це може призвести до сценаріїв, які складно тестувати та визначати.
+
+Однак (одначе), Ви все одно можете зробити це в **FastAPI**, використовуючи один із внутрішніх інструментів Starlette.
+
+Документація все ще працюватиме, хоча й не додаватиме опису про те, що параметр повинен містити шлях.
+
+### Конвертер шляху
+
+Використовуючи опцію безпосередньо зі Starlette, Ви можете оголосити *параметр шляху*, що містить *шлях*, використовуючи URL на кшталт:
+
+```
+/files/{file_path:path}
+```
+У цьому випадку ім'я параметра — `file_path`, а остання частина `:path` вказує на те, що параметр повинен відповідати будь-якому *шляху*.
+
+Отже, Ви можете використати його так:
+
+{* ../../docs_src/path_params/tutorial004.py hl[6] *}
+
+/// tip | Порада
+
+Вам може знадобитися, щоб параметр містив `/home/johndoe/myfile.txt` із початковою косою рискою (`/`).
+
+У такому випадку URL виглядатиме так: `/files//home/johndoe/myfile.txt`, із подвійною косою рискою (`//`) між `files` і `home`.
+
+///
+
+## Підсумок
+
+З **FastAPI**, використовуючи короткі, інтуїтивно зрозумілі та стандартні оголошення типів Python, Ви отримуєте:
+
+* Підтримку в редакторі: перевірка помилок, автодоповнення тощо.
+* "
Парсинг" даних
+* Валідацію даних
+* Анотацію API та автоматичну документацію
+
+І вам потрібно оголосити їх лише один раз.
+
+Це, ймовірно, основна видима перевага **FastAPI** порівняно з альтернативними фреймворками (окрім високої продуктивності).
diff --git a/docs/uk/docs/tutorial/query-param-models.md b/docs/uk/docs/tutorial/query-param-models.md
new file mode 100644
index 000000000..97eb82fa1
--- /dev/null
+++ b/docs/uk/docs/tutorial/query-param-models.md
@@ -0,0 +1,68 @@
+# Моделі Query параметрів
+
+Якщо у Вас є група **query параметрів**, які пов’язані між собою, Ви можете створити **Pydantic-модель** для їх оголошення.
+
+Це дозволить Вам **повторно використовувати модель** у **різних місцях**, а також оголошувати перевірки та метадані для всіх параметрів одночасно. 😎
+
+/// note | Примітка
+
+Ця можливість підтримується, починаючи з версії FastAPI `0.115.0`. 🤓
+
+///
+
+## Query параметри з Pydantic-моделлю
+
+Оголосіть **query параметри**, які Вам потрібні, у **Pydantic-моделі**, а потім оголосіть цей параметр як `Query`:
+
+{* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *}
+
+**FastAPI** буде **витягувати** дані для **кожного поля** з **query параметрів** у запиті та передавати їх у визначену вами Pydantic-модель.
+
+## Перевірте документацію
+
+Ви можете побачити параметри запиту в UI документації за `/docs`:
+
+
+

+
+
+## Заборона зайвих Query параметрів
+
+У деяких особливих випадках (ймовірно, не дуже поширених) Ви можете захотіти **обмежити** query параметри, які дозволено отримувати.
+
+Ви можете використати конфігурацію моделі Pydantic, щоб заборонити (`forbid`) будь-які зайві (`extra`) поля:
+
+{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *}
+
+Якщо клієнт спробує надіслати **зайві** дані у **query параметрах**, він отримає **помилку**.
+
+Наприклад, якщо клієнт спробує надіслати query параметр `tool` зі значенням `plumbus`, як у цьому запиті:
+
+```http
+https://example.com/items/?limit=10&tool=plumbus
+```
+
+Він отримає відповідь з **помилкою**, яка повідомить, що query параметр `tool ` не дозволено:
+
+```json
+{
+ "detail": [
+ {
+ "type": "extra_forbidden",
+ "loc": ["query", "tool"],
+ "msg": "Extra inputs are not permitted",
+ "input": "plumbus"
+ }
+ ]
+}
+```
+
+## Підсумок
+
+Ви можете використовувати **Pydantic-моделі** для оголошення **query параметрів** у **FastAPI**. 😎
+
+/// tip | Підказка
+
+Спойлер: Ви також можете використовувати Pydantic-моделі для оголошення cookie та заголовків, але про це Ви дізнаєтеся пізніше в цьому посібнику. 🤫
+
+///
diff --git a/docs/uk/docs/tutorial/query-params-str-validations.md b/docs/uk/docs/tutorial/query-params-str-validations.md
new file mode 100644
index 000000000..cd3f4ad93
--- /dev/null
+++ b/docs/uk/docs/tutorial/query-params-str-validations.md
@@ -0,0 +1,491 @@
+# Query параметри та валідація рядків
+
+**FastAPI** дозволяє оголошувати додаткову інформацію та виконувати валідацію для Ваших параметрів.
+
+Розглянемо цей додаток як приклад:
+
+{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *}
+
+Query параметр `q` має тип `str | None`, що означає, що він може бути як `str`, так і `None`. За замовчуванням він має значення `None`, тому FastAPI розуміє, що цей параметр не є обов'язковим.
+
+/// note | Примітка
+
+FastAPI знає, що `q` не є обов’язковим, завдяки значенню за замовчуванням `= None`.
+
+Використання `str | None` дозволить Вашому редактору коду надавати кращу підтримку та виявляти помилки.
+
+///
+
+## Додаткова валідація
+
+Ми хочемо, щоб навіть якщо `q` є необов’язковим, **його довжина не перевищувала 50 символів**, якщо він все ж буде переданий.
+
+### Імпорт `Query` та `Annotated`
+
+Щоб це зробити, спочатку імпортуємо:
+
+* `Query` з `fastapi`
+* `Annotated` з `typing`
+
+{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *}
+
+/// info | Інформація
+
+FastAPI додав підтримку `Annotated` (і почав рекомендувати його) у версії 0.95.0.
+
+Якщо у Вас старіша версія, під час використання `Annotated` можуть виникати помилки.
+
+Переконайтеся, що Ви [оновили версію FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} до принаймні 0.95.1, перш ніж використовувати `Annotated`.
+
+///
+
+## Використання `Annotated` у типі параметра `q`
+
+Пам’ятаєте, як я раніше розповідав, що `Annotated` можна використовувати для додавання метаданих до параметрів у [Вступі до типів Python](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}?
+
+Зараз саме час використати його разом із FastAPI. 🚀
+
+Раніше ми мали таку анотацію типу:
+
+//// tab | Python 3.10+
+
+```Python
+q: str | None = None
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python
+q: Union[str, None] = None
+```
+
+////
+
+Тепер ми загорнемо її у `Annotated`, і отримаємо:
+
+//// tab | Python 3.10+
+
+```Python
+q: Annotated[str | None] = None
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python
+q: Annotated[Union[str, None]] = None
+```
+
+////
+
+Обидві ці версії означають одне й те саме: `q` — це параметр, який може бути `str` або `None`, і за замовчуванням має значення `None`.
+
+А тепер переходимо до цікавого! 🎉
+
+## Додавання `Query` до `Annotated` у параметр `q`
+
+Тепер, коли у нас є `Annotated`, де ми можемо додавати додаткову інформацію (зокрема валідацію), додамо `Query` всередину `Annotated` і встановимо параметр `max_length` у `50`:
+
+{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *}
+
+Зверніть увагу, що значення за замовчуванням усе ще `None`, тому параметр залишається необов'язковим.
+
+Але тепер, додавши `Query(max_length=50)` всередину `Annotated`, ми повідомляємо FastAPI, що хочемо **додаткову валідацію** для цього значення — воно має містити максимум 50 символів. 😎
+
+/// tip | Підказка
+
+Ми використовуємо `Query()`, оскільки це **query параметр**. Далі ми розглянемо інші варіанти, як-от `Path()`, `Body()`, `Header()` та `Cookie()`, які приймають ті самі аргументи, що й `Query()`.
+
+///
+
+Тепер FastAPI:
+
+* **Перевірить** дані, щоб переконатися, що їхня довжина не перевищує 50 символів
+* Покажe **чітку помилку** клієнту, якщо дані недійсні
+* **Задокументує** параметр в OpenAPI-схемі *операції шляху* (що відобразиться в **автоматично згенерованій документації**)
+
+## Альтернативний (застарілий) метод: Query як значення за замовчуванням
+
+У попередніх версіях FastAPI (до
0.95.0) `Query` використовувався як значення за замовчуванням для параметра, а не всередині `Annotated`. Ви, ймовірно, побачите код, який використовує цей підхід, тому варто розглянути його.
+
+/// tip | Підказка
+
+Для нового коду та коли це можливо, використовуйте `Annotated`, як показано вище. Це має багато переваг (пояснених нижче) і не має недоліків. 🍰
+
+///
+
+Раніше ми писали `Query()` як значення за замовчуванням для параметра функції, встановлюючи `max_length` у 50:
+
+{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *}
+
+Оскільки в цьому випадку (без `Annotated`) нам потрібно замінити `None` у функції на `Query()`, тепер ми повинні явно встановити значення за замовчуванням через параметр `Query(default=None)`. Це виконує ту саму роль визначення значення за замовчуванням (принаймні для FastAPI).
+
+Таким чином:
+
+```Python
+q: str | None = Query(default=None)
+```
+
+...робить параметр необов’язковим зі значенням за замовчуванням `None`, що еквівалентно:
+
+
+```Python
+q: str | None = None
+```
+Але у версії з `Query` ми явно вказуємо, що це query параметр.
+
+Далі ми можемо передавати `Query` додаткові параметри, зокрема `max_length`, який застосовується до рядків:
+
+```Python
+q: str | None = Query(default=None, max_length=50)
+```
+
+Це забезпечить валідацію даних, виведе зрозумілу помилку у разі недійсних даних і задокументує параметр у схемі OpenAPI *операції шляху*.
+
+### `Query` як значення за замовчуванням або всередині `Annotated`
+
+Важливо пам’ятати, якщо використовувати `Query` всередині `Annotated`, не можна задавати параметр `default` у `Query`.
+
+Замість цього використовуйте значення за замовчуванням у самій функції. Інакше це буде нелогічно.
+
+Наприклад, цей варіант є некоректним:
+
+```Python
+q: Annotated[str, Query(default="rick")] = "morty"
+```
+
+...тому, що не зрозуміло, яке значення має бути значенням за замовчуванням: `"rick"` чи `"morty"`.
+
+Коректні варіанти:
+
+```Python
+q: Annotated[str, Query()] = "rick"
+```
+
+...або у старих кодових базах Ви знайдете:
+
+```Python
+q: str = Query(default="rick")
+```
+
+### Переваги використання `Annotated`
+
+**Використання `Annotated` є рекомендованим** замість задання значення за замовчуванням у параметрах функції, оскільки воно **краще** з кількох причин. 🤓
+
+Значення **за замовчуванням** параметра **функції** є його **фактичним значенням за замовчуванням**, що є більш інтуїтивним у Python загалом. 😌
+
+Ви можете **викликати** ту саму функцію **в інших місцях** без FastAPI, і вона **працюватиме очікувано**. Якщо параметр є **обов’язковим** (без значення за замовчуванням), Ваш **редактор** повідомить про помилку, а **Python** також видасть помилку, якщо Ви виконаєте функцію без передавання цього параметра.
+
+Якщо Ви не використовуєте `Annotated`, а використовуєте **(старий) стиль значень за замовчуванням**, то при виклику цієї функції без FastAPI **в інших місцях**, потрібно **не забути** передати їй аргументи, інакше значення будуть відрізнятися від очікуваних (наприклад, Ви отримаєте `QueryInfo` або подібне замість `str`). Ваш редактор не повідомить про помилку, і Python також не видасть помилку при запуску функції, поки не виникне помилка під час виконання операцій усередині.
+
+Оскільки `Annotated` може містити кілька анотацій метаданих, Ви навіть можете використовувати ту саму функцію з іншими інструментами, такими як
Typer. 🚀
+
+## Додавання додаткових валідацій
+
+Ви також можете додати параметр `min_length`:
+
+{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *}
+
+## Додавання регулярних виразів
+
+Ви можете визначити
регулярний вираз pattern, якому має відповідати параметр:
+
+{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
+
+Цей конкретний шаблон регулярного виразу перевіряє, що отримане значення параметра:
+
+* `^`: починається з наступних символів, перед якими немає інших символів.
+* `fixedquery`: точно відповідає значенню `fixedquery`.
+* `$`: закінчується тут, після `fixedquery` немає жодних символів.
+
+Якщо Ви почуваєтеся розгублено щодо **"регулярних виразів"**, не хвилюйтеся. Вони є складною темою для багатьох людей. Ви все одно можете зробити багато речей без їх використання.
+
+Але тепер Ви знаєте, що коли вони знадобляться, їх можна застосовувати у **FastAPI**.
+
+### Pydantic v1 `regex` замість `pattern`
+
+До версії Pydantic 2 і FastAPI 0.100.0 параметр називався `regex` замість `pattern`, але тепер він застарів.
+
+Ви все ще можете зустріти код, який використовує його:
+
+//// tab | Pydantic v1
+
+{* ../../docs_src/query_params_str_validations/tutorial004_regex_an_py310.py hl[11] *}
+
+////
+
+Але майте на увазі, що він є застарілим і його слід оновити до нового параметра `pattern`. 🤓
+
+## Значення за замовчуванням
+
+Ви можете використовувати значення за замовчуванням, відмінні від `None`.
+
+Наприклад, якщо Ви хочете оголосити параметр запиту `q` з `min_length` `3` і значенням за замовчуванням `"fixedquery"`:
+
+{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *}
+
+/// note | Технічні деталі
+
+Наявність значення за замовчуванням будь-якого типу, включаючи `None`, робить параметр необов’язковим (not required).
+
+///
+
+## Обов’язкові параметри
+
+Якщо нам не потрібно вказувати додаткові перевірки або метадані, ми можемо зробити параметр `q` обов’язковим, просто не оголошуючи значення за замовчуванням, наприклад:
+
+```Python
+q: str
+```
+
+замість:
+
+```Python
+q: str | None = None
+```
+
+Але тепер ми оголошуємо його з `Query`, наприклад:
+
+//// tab | Annotated
+
+```Python
+q: Annotated[str | None, Query(min_length=3)] = None
+```
+
+////
+
+Тому, якщо Вам потрібно зробити значення обов’язковим, використовуючи `Query`, просто не вказуйте значення за замовчуванням:
+
+{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
+
+### Обов’язкове значення, яке може бути `None`
+
+Ви можете вказати, що параметр може приймати `None`, але при цьому залишається обов’язковим. Це змусить клієнтів надіслати значення, навіть якщо воно дорівнює `None`.
+
+Щоб зробити це, оголосіть, що `None` є допустимим типом, але не вказуйте значення за замовчуванням:
+
+{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *}
+
+## Список параметрів запиту / кілька значень
+
+Якщо Ви визначаєте параметр запиту за допомогою `Query`, Ви також можете дозволити отримання списку значень, тобто дозволити отримання кількох значень.
+
+Наприклад, щоб дозволити параметру запиту `q` з'являтися кілька разів в URL, можна написати:
+
+{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *}
+
+Тоді, у випадку запиту за URL:
+
+```
+http://localhost:8000/items/?q=foo&q=bar
+```
+
+Ви отримаєте кілька значень *query параметра* `q` (`foo` і `bar`) у вигляді списку `list` в Python у Вашій *функції обробки шляху*, у *параметрі функції* `q`.
+
+Отже, відповідь на цей URL буде:
+
+```JSON
+{
+ "q": [
+ "foo",
+ "bar"
+ ]
+}
+```
+
+/// tip | Підказка
+
+Щоб оголосити параметр запиту з типом `list`, як у наведеному вище прикладі, потрібно явно використовувати `Query`, інакше він буде інтерпретований як тіло запиту.
+
+///
+
+Інтерактивна API-документація оновиться відповідно, дозволяючи передавати кілька значень:
+
+

+
+### Список параметрів запиту / кілька значень за замовчуванням
+
+Ви також можете визначити значення за замовчуванням для `list`, якщо жодне значення не було передане:
+
+{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}
+
+Якщо Ви перейдете за посиланням:
+
+```
+http://localhost:8000/items/
+```
+
+то значення `q` за замовчуванням буде: `["foo", "bar"]`, і Ваша відповідь виглядатиме так:
+
+```JSON
+{
+ "q": [
+ "foo",
+ "bar"
+ ]
+}
+```
+
+#### Використання тільки `list`
+
+Ви також можете використовувати `list` без уточнення типу, замість `list[str]`:
+
+{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
+
+/// note | Технічні деталі
+
+Майте на увазі, що в цьому випадку FastAPI не перевірятиме вміст списку.
+
+Наприклад, `list[int]` перевірятиме (і документуватиме), що всі елементи списку є цілими числами. Але `list` без уточнення цього не робитиме.
+
+///
+
+## Додавання додаткових метаданих
+
+Ви можете додати більше інформації про параметр.
+
+Ця інформація буде включена у згенерований OpenAPI та використана в інтерфейсах документації та зовнішніх інструментах.
+
+/// note | Технічні деталі
+
+Майте на увазі, що різні інструменти можуть мати різний рівень підтримки OpenAPI.
+
+Деякі з них можуть ще не відображати всю додаткову інформацію, хоча в більшості випадків ця функція вже запланована для розробки.
+
+///
+
+Ви можете додати `title` :
+
+{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *}
+
+А також `description`:
+
+{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *}
+
+## Аліаси параметрів
+
+Уявіть, що Ви хочете, щоб параметр називався `item-query`.
+
+Наприклад:
+
+```
+http://127.0.0.1:8000/items/?item-query=foobaritems
+```
+
+Але `item-query` — це некоректна назва змінної в Python.
+
+Найближчий допустимий варіант — `item_query`.
+
+Проте Вам потрібно, щоб параметр залишався саме `item-query`...
+
+У такому випадку можна оголосити `alias`, і саме він буде використовуватися для отримання значення параметра:
+
+{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *}
+
+## Виведення параметрів як застарілих
+
+Припустимо, що Ви більше не хочете використовувати цей параметр.
+
+Вам потрібно залишити його на деякий час, оскільки ним користуються клієнти, але Ви хочете, щоб документація чітко показувала, що він є
застарілим.
+
+Тоді Ви можете передати параметр `deprecated=True` до `Query`:
+
+{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *}
+
+Документація буде показувати це таким чином:
+
+

+
+## Виняток параметрів з OpenAPI
+
+Щоб виключити параметр запиту зі згенерованої схеми OpenAPI (і, таким чином, з автоматичних систем документації), встановіть параметр `include_in_schema` для `Query` в `False`:
+
+{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *}
+
+## Кастомна валідація
+
+Можуть бути випадки, коли Вам потрібно провести **кастомну валідацію**, яку не можна реалізувати за допомогою параметрів, показаних вище.
+
+У таких випадках ви можете використати **кастомну функцію валідації**, яка буде застосована після звичайної валідації (наприклад, після перевірки, що значення є типом `str`).
+
+Це можна досягти за допомогою
Pydantic's `AfterValidator` в середині `Annotated`.
+
+/// tip | Підказка
+
+Pydantic також має
`BeforeValidator` та інші. 🤓
+
+///
+
+Наприклад, цей кастомний валідатор перевіряє, чи починається ID елемента з `isbn-` для номера книги
ISBN або з `imdb-` для ID URL фільму на
IMDB:
+
+{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
+
+/// info | Інформація
+
+Це доступно з версії Pydantic 2 або вище. 😎
+
+///
+
+/// tip | Підказка
+
+Якщо Вам потрібно виконати будь-яку валідацію, яка вимагає взаємодії з будь-яким **зовнішнім компонентом**, таким як база даних чи інший API, ви повинні замість цього використовувати **FastAPI Dependencies**. Ви дізнаєтесь про них пізніше.
+
+Ці кастомні валідатори використовуються для речей, які можна перевірити лише з **тими даними**, що надані в запиті.
+
+///
+
+### Зрозумійте цей код
+
+Головний момент – це використання **`AfterValidator` з функцією всередині `Annotated`**. Можете пропустити цю частину, якщо хочете. 🤸
+
+---
+
+Але якщо Вам цікаво розібратися в цьому конкретному прикладі коду і Вам ще не набридло, ось кілька додаткових деталей.
+
+#### Рядок із `value.startswith()`
+
+Звернули увагу? Рядок із `value.startswith()` може приймати кортеж, і тоді він перевірятиме кожне значення в кортежі:
+
+{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *}
+
+#### Випадковий елемент
+
+За допомогою `data.items()` ми отримуємо
ітерабельний об'єкт із кортежами, що містять ключ і значення для кожного елемента словника.
+
+Ми перетворюємо цей ітерабельний об'єкт у звичайний `list` за допомогою `list(data.items())`.
+
+Потім, використовуючи `random.choice()`, ми можемо отримати випадкове значення зі списку, тобто отримуємо кортеж із `(id, name)`. Це може бути щось на зразок `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`.
+
+Далі ми **присвоюємо ці два значення** кортежу змінним `id` і `name`.
+
+Тож, якщо користувач не вказав ID елемента, він все одно отримає випадкову рекомендацію.
+
+...і все це реалізовано в **одному рядку коду**. 🤯 Хіба не прекрасний Python? 🐍
+
+{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *}
+
+## Підсумок
+
+Ви можете оголошувати додаткові валідації та метаінформацію для своїх параметрів.
+
+Загальні валідації та метаінформація:
+
+* `alias`
+* `title`
+* `description`
+* `deprecated`
+
+Валідації, специфічні для рядків:
+
+* `min_length`
+* `max_length`
+* `pattern`
+
+Кастомні валідації за допомогою `AfterValidator`.
+
+У цих прикладах Ви побачили, як оголошувати валідації для значень `str`.
+
+Дивіться наступні розділи, щоб дізнатися, як оголошувати валідації для інших типів, наприклад чисел.
diff --git a/docs/uk/docs/tutorial/query-params.md b/docs/uk/docs/tutorial/query-params.md
new file mode 100644
index 000000000..16bb42af3
--- /dev/null
+++ b/docs/uk/docs/tutorial/query-params.md
@@ -0,0 +1,192 @@
+# Query Параметри
+
+Коли Ви оголошуєте інші параметри функції, які не є частиною параметрів шляху, вони автоматично інтерпретуються як "query" параметри.
+
+{* ../../docs_src/query_params/tutorial001.py hl[9] *}
+
+Query параметри — це набір пар ключ-значення, що йдуть після символу `?` в URL, розділені символами `&`.
+
+Наприклад, в URL:
+
+```
+http://127.0.0.1:8000/items/?skip=0&limit=10
+```
+
+...query параметрами є:
+
+* `skip`: зі значенням `0`
+* `limit`: зі значенням `10`
+
+Оскільки вони є частиною URL, вони "за замовчуванням" є рядками.
+
+Але коли Ви оголошуєте їх із типами Python (у наведеному прикладі як `int`), вони перетворюються на цей тип і проходять перевірку відповідності.
+
+Увесь той самий процес, який застосовується до параметрів шляху, також застосовується до query параметрів:
+
+* Підтримка в редакторі (автодоповнення, перевірка помилок)
+*
"Парсинг" даних
+* Валідація даних
+* Автоматична документація
+
+
+## Значення за замовчуванням
+
+Оскільки query параметри не є фіксованою частиною шляху, вони можуть бути необов’язковими та мати значення за замовчуванням.
+
+У наведеному вище прикладі вони мають значення за замовчуванням: `skip=0` і `limit=10`.
+
+Отже, результат переходу за URL:
+
+```
+http://127.0.0.1:8000/items/
+```
+буде таким самим, як і перехід за посиланням:
+
+```
+http://127.0.0.1:8000/items/?skip=0&limit=10
+```
+
+Але якщо Ви перейдете, наприклад, за посиланням:
+
+```
+http://127.0.0.1:8000/items/?skip=20
+```
+
+Значення параметрів у вашій функції будуть такими:
+
+* `skip=20`: оскільки Ви вказали його в URL
+* `limit=10`: оскільки це значення за замовчуванням
+
+## Необов'язкові параметри
+
+Аналогічно, Ви можете оголосити необов’язкові query параметри, встановивши для них значення за замовчуванням `None`:
+
+{* ../../docs_src/query_params/tutorial002_py310.py hl[7] *}
+
+У цьому випадку параметр функції `q` буде необов’язковим і за замовчуванням матиме значення `None`.
+
+/// check | Примітка
+
+Також зверніть увагу, що **FastAPI** достатньо розумний, щоб визначити, що параметр шляху `item_id` є параметром шляху, а `q` — ні, отже, це query параметр.
+
+///
+
+## Перетворення типу Query параметра
+
+Ви також можете оголошувати параметри типу `bool`, і вони будуть автоматично конвертовані:
+
+{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *}
+
+У цьому випадку, якщо Ви звернетесь до:
+
+
+```
+http://127.0.0.1:8000/items/foo?short=1
+```
+
+або
+
+```
+http://127.0.0.1:8000/items/foo?short=True
+```
+
+або
+
+```
+http://127.0.0.1:8000/items/foo?short=true
+```
+
+або
+
+```
+http://127.0.0.1:8000/items/foo?short=on
+```
+
+або
+
+```
+http://127.0.0.1:8000/items/foo?short=yes
+```
+
+або будь-який інший варіант написання (великі літери, перша літера велика тощо), ваша функція побачить параметр `short` зі значенням `True` з типом даних `bool`. В іншому випадку – `False`.
+
+## Кілька path і query параметрів
+
+Ви можете одночасно оголошувати кілька path і query параметрів, і **FastAPI** автоматично визначить, який з них до чого належить.
+
+
+Не потрібно дотримуватись певного порядку їх оголошення.
+
+Вони визначаються за назвою:
+
+{* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *}
+
+## Обов’язкові Query параметри
+
+Якщо Ви оголошуєте значення за замовчуванням для параметрів, які не є path-параметрами (у цьому розділі ми бачили поки що лише path параметри), тоді вони стають необов’язковими.
+
+Якщо Ви не хочете вказувати конкретні значення, але хочете зробити параметр опціональним, задайте `None` як значення за замовчуванням.
+
+Але якщо Ви хочете зробити query параметр обов’язковим, просто не вказуйте для нього значення за замовчуванням:
+
+{* ../../docs_src/query_params/tutorial005.py hl[6:7] *}
+
+Тут `needy` – обов’язковий query параметр типу `str`.
+
+Якщо Ви відкриєте у браузері URL-адресу:
+
+```
+http://127.0.0.1:8000/items/foo-item
+```
+
+...без додавання обов’язкового параметра `needy`, Ви побачите помилку:
+
+```JSON
+{
+ "detail": [
+ {
+ "type": "missing",
+ "loc": [
+ "query",
+ "needy"
+ ],
+ "msg": "Field required",
+ "input": null,
+ "url": "https://errors.pydantic.dev/2.1/v/missing"
+ }
+ ]
+}
+```
+
+Оскільки `needy` є обов’язковим параметром, вам потрібно вказати його в URL:
+
+```
+http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
+```
+
+...цей запит поверне:
+
+```JSON
+{
+ "item_id": "foo-item",
+ "needy": "sooooneedy"
+}
+```
+
+
+Звичайно, Ви можете визначити деякі параметри як обов’язкові, інші зі значенням за замовчуванням, а ще деякі — повністю опціональні:
+
+{* ../../docs_src/query_params/tutorial006_py310.py hl[8] *}
+
+У цьому випадку є 3 query параметри:
+
+* `needy`, обов’язковий `str`.
+* `skip`, `int` зі значенням за замовчуванням `0`.
+* `limit`, опціональний `int`.
+
+
+/// tip | Підказка
+
+Ви також можете використовувати `Enum`-и, так само як і з [Path Parameters](path-params.md#predefined-values){.internal-link target=_blank}.
+
+///
diff --git a/docs/uk/docs/tutorial/request-files.md b/docs/uk/docs/tutorial/request-files.md
new file mode 100644
index 000000000..18b7cc01c
--- /dev/null
+++ b/docs/uk/docs/tutorial/request-files.md
@@ -0,0 +1,175 @@
+# Запит файлів
+
+Ви можете визначити файли, які будуть завантажуватися клієнтом, використовуючи `File`.
+
+/// info | Інформація
+
+Щоб отримувати завантажені файли, спочатку встановіть
python-multipart.
+
+Переконайтеся, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його та встановили пакет, наприклад:
+
+```console
+$ pip install python-multipart
+```
+
+Це необхідно, оскільки завантажені файли передаються у вигляді "форматованих даних форми".
+
+///
+
+## Імпорт `File`
+
+Імпортуйте `File` та `UploadFile` з `fastapi`:
+
+{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
+
+## Визначення параметрів `File`
+
+Створіть параметри файлів так само як Ви б створювали `Body` або `Form`:
+
+{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *}
+
+/// info | Інформація
+
+`File` — це клас, який безпосередньо успадковує `Form`.
+
+Але пам’ятайте, що коли Ви імпортуєте `Query`, `Path`, `File` та інші з `fastapi`, це насправді функції, які повертають спеціальні класи.
+
+///
+
+/// tip | Підказка
+
+Щоб оголосити тіла файлів, Вам потрібно використовувати `File`, тому що інакше параметри будуть інтерпретовані як параметри запиту або параметри тіла (JSON).
+
+///
+
+Файли будуть завантажені у вигляді "форматованих даних форми".
+
+Якщо Ви оголосите тип параметра функції обробника маршруту як `bytes`, **FastAPI** прочитає файл за Вас, і Ви отримаєте його вміст у вигляді `bytes`.
+
+Однак майте на увазі, що весь вміст буде збережено в пам'яті. Це працюватиме добре для малих файлів.
+
+Але в деяких випадках Вам може знадобитися `UploadFile`.
+
+## Параметри файлу з `UploadFile`
+
+Визначте параметр файлу з типом `UploadFile`:
+
+{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *}
+
+Використання `UploadFile` має кілька переваг перед `bytes`:
+
+* Вам не потрібно використовувати `File()` у значенні за замовчуванням параметра.
+* Використовується "буферизований" файл:
+ * Файл зберігається в пам'яті до досягнення певного обмеження, після чого він записується на диск.
+* Це означає, що він добре працює для великих файлів, таких як зображення, відео, великі двійкові файли тощо, не споживаючи всю пам'ять.
+Ви можете отримати метадані про завантажений файл.
+* Він має
file-like `асинхронний файловий інтерфейс` interface.
+* Він надає фактичний об'єкт Python
`SpooledTemporaryFile`, який можна передавати безпосередньо іншим бібліотекам.
+
+### `UploadFile`
+
+`UploadFile` має такі атрибути:
+
+* `filename`: Рядок `str` з оригінальною назвою файлу, який був завантажений (наприклад, `myimage.jpg`).
+* `content_type`: Рядок `str` з MIME-типом (наприклад, `image/jpeg`).
+* `file`: Об'єкт
SpooledTemporaryFile (
файлоподібний об'єкт). Це фактичний файловий об'єкт Python, який можна безпосередньо передавати іншим функціям або бібліотекам, що очікують "файлоподібний" об'єкт.
+
+`UploadFile` має такі асинхронні `async` методи. Вони викликають відповідні методи файлу під капотом (використовуючи внутрішній `SpooledTemporaryFile`).
+
+* `write(data)`: Записує `data` (`str` або `bytes`) у файл.
+* `read(size)`: Читає `size` (`int`) байтів/символів з файлу.
+* `seek(offset)`: Переміщується до позиції `offset` (`int`) у файлі.
+ * Наприклад, `await myfile.seek(0)` поверне курсор на початок файлу.
+ * This is especially useful if you run `await myfile.read()` once and then need to read the contents again. Це особливо корисно, якщо Ви виконуєте await `await myfile.read()` один раз, а потім потрібно знову прочитати вміст.
+* `close()`: Закриває файл.
+
+Оскільки всі ці методи є асинхронними `async`, Вам потрібно використовувати "await":
+
+Наприклад, всередині `async` *функції обробки шляху* Ви можете отримати вміст за допомогою:
+
+```Python
+contents = await myfile.read()
+```
+Якщо Ви знаходитесь у звичайній `def` *функції обробки шляху*, Ви можете отримати доступ до `UploadFile.file` безпосередньо, наприклад:
+
+```Python
+contents = myfile.file.read()
+```
+
+/// note | Технічні деталі `async`
+
+Коли Ви використовуєте `async` методи, **FastAPI** виконує файлові операції у пулі потоків та очікує їх завершення.
+
+///
+
+/// note | Технічні деталі Starlette
+
+`UploadFile` у **FastAPI** успадковується безпосередньо від `UploadFile` у **Starlette**, але додає деякі необхідні частини, щоб зробити його сумісним із **Pydantic** та іншими компонентами FastAPI.
+
+///
+
+## Що таке "Form Data"
+
+Спосіб, у який HTML-форми (`
`) надсилають дані на сервер, зазвичай використовує "спеціальне" кодування, відмінне від JSON.
+
+**FastAPI** забезпечує правильне зчитування цих даних з відповідної частини запиту, а не з JSON.
+
+/// note | Технічні деталі
+
+Дані з форм зазвичай кодуються за допомогою "media type" `application/x-www-form-urlencoded`, якщо вони не містять файлів.
+
+Але якщо форма містить файли, вона кодується у форматі `multipart/form-data`. Якщо Ви використовуєте `File`, **FastAPI** визначить, що потрібно отримати файли з відповідної частини тіла запиту.
+
+Щоб дізнатися більше про ці типи кодування та формові поля, ознайомтеся з
документацією MDN щодо POST
.
+
+///
+
+/// warning | Увага
+
+Ви можете оголосити кілька параметрів `File` і `Form` в *операції шляху*, але Ви не можете одночасно оголошувати поля `Body`, які мають надходити у форматі JSON, оскільки тіло запиту буде закодоване у форматі `multipart/form-data`, а не `application/json`.
+
+Це не обмеження **FastAPI**, а особливість протоколу HTTP.
+
+///
+
+## Опціональне Завантаження Файлів
+
+Файл можна зробити необов’язковим, використовуючи стандартні анотації типів і встановлюючи значення за замовчуванням `None`:
+
+{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *}
+
+## `UploadFile` із Додатковими Мета Даними
+
+Ви також можете використовувати `File()` разом із `UploadFile`, наприклад, для встановлення додаткових метаданих:
+
+{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}
+
+## Завантаження Кількох Файлів
+
+Можна завантажувати кілька файлів одночасно.
+
+Вони будуть пов’язані з одним і тим самим "form field", який передається у вигляді "form data".
+
+Щоб це реалізувати, потрібно оголосити список `bytes` або `UploadFile`:
+
+{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *}
+
+Ви отримаєте, як і було оголошено, `list` із `bytes` або `UploadFile`.
+
+/// note | Технічні деталі
+
+Ви також можете використати `from starlette.responses import HTMLResponse`.
+
+**FastAPI** надає ті ж самі `starlette.responses`, що й `fastapi.responses`, для зручності розробників. Однак більшість доступних відповідей надходять безпосередньо від Starlette.
+
+///
+
+### Завантаження декількох файлів із додатковими метаданими
+
+Так само як і раніше, Ви можете використовувати `File()`, щоб встановити додаткові параметри навіть для `UploadFile`:
+
+{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *}
+
+## Підсумок
+
+Використовуйте `File`, `bytes`та `UploadFile`, щоб оголошувати файли для завантаження у запитах, які надсилаються у вигляді form data.
diff --git a/docs/uk/docs/tutorial/request-form-models.md b/docs/uk/docs/tutorial/request-form-models.md
new file mode 100644
index 000000000..7f5759e79
--- /dev/null
+++ b/docs/uk/docs/tutorial/request-form-models.md
@@ -0,0 +1,78 @@
+# Моделі форм (Form Models)
+
+У FastAPI Ви можете використовувати **Pydantic-моделі** для оголошення **полів форми**.
+
+/// info | Інформація
+
+Щоб використовувати форми, спочатку встановіть
python-multipart.
+
+Переконайтеся, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили бібліотеку, наприклад:
+
+```console
+$ pip install python-multipart
+```
+
+///
+
+/// note | Підказка
+
+Ця функція підтримується, починаючи з FastAPI версії `0.113.0`. 🤓
+
+///
+
+## Використання Pydantic-моделей для форм
+
+Вам просто потрібно оголосити **Pydantic-модель** з полями, які Ви хочете отримати як **поля форми**, а потім оголосити параметр як `Form`:
+
+{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *}
+
+**FastAPI** **витягне** дані для **кожного поля** з **формових даних** у запиті та надасть вам Pydantic-модель, яку Ви визначили.
+
+## Перевірка документації
+
+Ви можете перевірити це в UI документації за `/docs`:
+
+
+

+
+
+## Заборона додаткових полів форми
+
+У деяких особливих випадках (ймовірно, рідко) Ви можете **обмежити** форму лише тими полями, які були оголошені в Pydantic-моделі, і **заборонити** будь-які **додаткові** поля.
+
+/// note | Підказка
+
+Ця функція підтримується, починаючи з FastAPI версії `0.114.0`. 🤓
+
+///
+
+Ви можете використати конфігурацію Pydantic-моделі, щоб заборонити `forbid` будь-які додаткові `extra` поля:
+
+{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *}
+
+Якщо клієнт спробує надіслати додаткові дані, він отримає **відповідь з помилкою**.
+
+Наприклад, якщо клієнт спробує надіслати наступні поля форми:
+
+* `username`: `Rick`
+* `password`: `Portal Gun`
+* `extra`: `Mr. Poopybutthole`
+
+Він отримає відповідь із помилкою, яка повідомляє, що поле `extra` не дозволено:
+
+```json
+{
+ "detail": [
+ {
+ "type": "extra_forbidden",
+ "loc": ["body", "extra"],
+ "msg": "Extra inputs are not permitted",
+ "input": "Mr. Poopybutthole"
+ }
+ ]
+}
+```
+
+## Підсумок
+
+Ви можете використовувати Pydantic-моделі для оголошення полів форми у FastAPI. 😎
diff --git a/docs/uk/docs/tutorial/request-forms-and-files.md b/docs/uk/docs/tutorial/request-forms-and-files.md
new file mode 100644
index 000000000..a089ef945
--- /dev/null
+++ b/docs/uk/docs/tutorial/request-forms-and-files.md
@@ -0,0 +1,41 @@
+# Запити з формами та файлами
+
+У FastAPI Ви можете одночасно отримувати файли та поля форми, використовуючи `File` і `Form`.
+
+/// info | Інформація
+
+Щоб отримувати завантажені файли та/або дані форми, спочатку встановіть
python-multipart.
+
+Переконайтеся, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили бібліотеку, наприклад:
+
+```console
+$ pip install python-multipart
+```
+
+///
+
+## Імпорт `File` та `Form`
+
+{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *}
+
+## Оголошення параметрів `File` та `Form`
+
+Створіть параметри файлів та форми так само як і для `Body` або `Query`:
+
+{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *}
+
+Файли та поля форми будуть завантажені як формові дані, і Ви отримаєте як файли, так і введені користувачем поля.
+
+Ви також можете оголосити деякі файли як `bytes`, а деякі як `UploadFile`.
+
+/// warning | Увага
+
+Ви можете оголосити кілька параметрів `File` і `Form` в операції *шляху*, але не можете одночасно оголошувати `Body`-поля, які очікуєте отримати у форматі JSON, оскільки запит матиме тіло, закодоване за допомогою `multipart/form-data`, а не `application/json`.
+
+Це не обмеження **FastAPI**, а частина протоколу HTTP.
+
+///
+
+## Підсумок
+
+Використовуйте `File` та `Form` разом, коли вам потрібно отримувати дані форми та файли в одному запиті.
diff --git a/docs/uk/docs/tutorial/request-forms.md b/docs/uk/docs/tutorial/request-forms.md
new file mode 100644
index 000000000..10c58a73e
--- /dev/null
+++ b/docs/uk/docs/tutorial/request-forms.md
@@ -0,0 +1,73 @@
+# Дані форми
+
+Якщо Вам потрібно отримувати поля форми замість JSON, Ви можете використовувати `Form`.
+
+/// info | Інформація
+
+Щоб використовувати форми, спочатку встановіть
`python-multipart`.
+
+Переконайтеся, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, і потім встановили бібліотеку, наприклад:
+
+```console
+$ pip install python-multipart
+```
+
+///
+
+## Імпорт `Form`
+
+Імпортуйте `Form` з `fastapi`:
+
+{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *}
+
+## Оголошення параметрів `Form`
+
+Створюйте параметри форми так само як Ви б створювали `Body` або `Query`:
+
+{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *}
+
+Наприклад, один зі способів використання специфікації OAuth2 (так званий "password flow") вимагає надсилати `username` та `password` як поля форми.
+
+
spec вимагає, щоб ці поля мали точні назви `username` і `password` та надсилалися у вигляді полів форми, а не JSON.
+
+З `Form` Ви можете оголошувати ті ж конфігурації, що і з `Body` (та `Query`, `Path`, `Cookie`), включаючи валідацію, приклади, псевдоніми (наприклад, `user-name` замість `username`) тощо.
+
+/// info | Інформація
+
+`Form` — це клас, який безпосередньо наслідується від `Body`.
+
+///
+
+/// tip | Порада
+
+Щоб оголосити тіло форми, потрібно явно використовувати `Form`, оскільки без нього параметри будуть інтерпретуватися як параметри запиту або тіла (JSON).
+
+///
+
+## Про "поля форми"
+
+HTML-форми (`
`) надсилають дані на сервер у "спеціальному" кодуванні, яке відрізняється від JSON.
+
+**FastAPI** подбає про те, щоб зчитати ці дані з правильного місця, а не з JSON.
+
+/// note | Технічні деталі
+
+Дані з форм зазвичай кодуються за допомогою "типу медіа" `application/x-www-form-urlencoded`.
+
+Але якщо форма містить файли, вона кодується як `multipart/form-data`. Ви дізнаєтеся про обробку файлів у наступному розділі.
+
+Якщо Ви хочете дізнатися більше про ці кодування та поля форм, зверніться до
MDN вебдокументації для POST
.
+
+///
+
+/// warning | Попередження
+
+Ви можете оголосити кілька параметрів `Form` в *операції шляху*, але не можете одночасно оголосити поля `Body`, які Ви очікуєте отримати у форматі JSON, оскільки тіло запиту буде закодовано у форматі `application/x-www-form-urlencoded`, а не `application/json`.
+
+Це не обмеження **FastAPI**, а частина HTTP-протоколу.
+
+///
+
+## Підсумок
+
+Використовуйте `Form` для оголошення вхідних параметрів у вигляді даних форми.
diff --git a/docs/uk/docs/tutorial/response-model.md b/docs/uk/docs/tutorial/response-model.md
new file mode 100644
index 000000000..def1f8a2d
--- /dev/null
+++ b/docs/uk/docs/tutorial/response-model.md
@@ -0,0 +1,358 @@
+# Модель відповіді — Тип, що повертається
+
+Ви можете оголосити тип, який використовуватиметься у відповіді, за допомогою *анотації типу, що повертається* *функцією операцією шляху* (path operation)
+
+**Анотацію типу** можна вказати так само як і для вхідних **параметрів** функції: це можуть бути моделі Pydantic, списки (lists), словники (dictionaries), скалярні значення, як-от цілі числа (integers), булеві значення (booleans) тощо.
+
+{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *}
+
+FastAPI використовуватиме цей тип, щоб:
+
+* **Перевірити правильність** повернених даних.
+ * Якщо дані не валідні (наприклад, відсутнє поле), це означає, що Ваш код додатку працює некоректно і не повертає те, що повинен. У такому випадку FastAPI поверне помилку сервера, замість того щоб віддати недопустимі дані. Так Ви та Ваші клієнти будете впевнені, що отримуєте очікувані дані у правильному форматі.
+
+* Додати **JSON Schema** відповіді до специфікації OpenAPI в *операціях шляху*.
+ * Це буде використано в **автоматичній документації**.
+ * А також інструментами, які автоматично генерують клієнтський код.
+
+Але найголовніше:
+
+* FastAPI **обмежить та відфільтрує** вихідні дані відповідно до типу, вказаного у відповіді.
+ * Це особливо важливо для **безпеки**. Деталі нижче.
+
+## Параметр `response_model`
+
+Іноді Вам потрібно або зручно повертати інші типи даних, ніж ті, що зазначені як тип відповіді.
+
+Наприклад, Ви можете **повертати словник** або об’єкт бази даних, але **оголосити модель Pydantic** як модель відповіді. Тоді модель Pydantic автоматично оброблятиме валідацію, документацію тощо.
+
+Якщо Ви додасте анотацію типу для повернення, редактор коду або mypy можуть поскаржитися, що функція повертає інший тип (наприклад, dict замість Item).
+
+У таких випадках можна скористатися параметром `response_model` в декораторі маршруту (наприклад, @app.get()).
+
+Параметр `response_model` працює з будь-яким *оператором шляху*:
+
+* `@app.get()`
+* `@app.post()`
+* `@app.put()`
+* `@app.delete()`
+* тощо.
+
+{* ../../docs_src/response_model/tutorial001_py310.py hl[17,22,24:27] *}
+
+/// note | Примітка
+
+Зверніть увагу, що `response_model` є параметром методу-декоратора (`get`, `post`, тощо), а не *функцією операцією шляху* (path operation function), як це робиться з параметрами або тілом запиту.
+
+///
+
+`response_model` приймає такий самий тип, який Ви б вказали для поля моделі Pydantic. Тобто це може бути як Pydantic-модель, так і, наприклад, `list` із моделей Pydantic — `List[Item]`.
+
+FastAPI використовуватиме `response_model` для створення документації, валідації даних та — найважливіше — **перетворення та фільтрації вихідних даних** згідно з оголошеним типом.
+
+/// tip | Порада
+
+Якщо у Вас увімкнено сувору перевірку типів у редакторі, mypy тощо, Ви можете оголосити тип повернення функції як `Any`.
+
+Таким чином, Ви повідомляєте редактору, що свідомо повертаєте будь-що. Але FastAPI усе одно виконуватиме створення документації, валідацію, фільтрацію тощо за допомогою параметра `response_model`.
+
+///
+
+### Пріоритет `response_model`
+
+Якщо Ви вказуєте і тип повернення, і `response_model`, то FastAPI використовуватиме `response_model` з пріоритетом.
+
+Таким чином, Ви можете додати правильні анотації типів до ваших функцій, навіть якщо вони повертають тип, відмінний від `response_model`. Це буде корисно для редакторів коду та інструментів, таких як mypy. І при цьому FastAPI продовжить виконувати валідацію даних, генерувати документацію тощо на основі `response_model`.
+
+Ви також можете використати `response_model=None`, щоб вимкнути створення моделі відповіді для цієї *операції шляху*. Це може знадобитися, якщо Ви додаєте анотації типів до об'єктів, які не є допустимими полями Pydantic — приклад цього Ви побачите в одному з наступних розділів.
+
+## Повернути ті самі вхідні дані
+
+Тут ми оголошуємо модель `UserIn`, яка містить звичайний текстовий пароль:
+
+{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *}
+
+/// info | Інформація
+
+Щоб використовувати `EmailStr`, спочатку встановіть
`email-validator`.
+
+Переконайтесь, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили пакет, наприклад:
+
+```console
+$ pip install email-validator
+```
+
+or with:
+
+```console
+$ pip install "pydantic[email]"
+```
+
+///
+
+І ми використовуємо цю модель, щоб оголосити і вхідні, і вихідні дані:
+
+{* ../../docs_src/response_model/tutorial002_py310.py hl[16] *}
+
+Тепер, коли браузер створює користувача з паролем, API поверне той самий пароль у відповіді.
+
+У цьому випадку це може не бути проблемою, адже саме користувач надіслав пароль.
+
+Але якщо ми використаємо цю ж модель для іншої операції шляху, ми можемо випадково надіслати паролі наших користувачів кожному клієнту.
+
+/// danger | Обережно
+
+Ніколи не зберігайте пароль користувача у відкритому вигляді та не надсилайте його у відповіді, якщо тільки Ви не знаєте всі ризики і точно розумієте, що робите.
+
+///
+
+## Додайте окрему вихідну модель
+
+Замість цього ми можемо створити вхідну модель з відкритим паролем і вихідну модель без нього:
+
+{* ../../docs_src/response_model/tutorial003_py310.py hl[9,11,16] *}
+
+Тут, навіть якщо *функція операції шляху* повертає об'єкт користувача, який містить пароль:
+
+{* ../../docs_src/response_model/tutorial003_py310.py hl[24] *}
+
+...ми оголосили `response_model` як нашу модель `UserOut`, яка не містить пароля:
+
+{* ../../docs_src/response_model/tutorial003_py310.py hl[22] *}
+
+Таким чином, **FastAPI** автоматично відфільтрує всі дані, які не вказані у вихідній моделі (за допомогою Pydantic).
+
+### `response_model` або тип повернення
+
+У цьому випадку, оскільки дві моделі різні, якщо ми анотуємо тип повернення функції як `UserOut`, редактор і такі інструменти, як mypy, видадуть помилку, бо фактично ми повертаємо інший тип.
+
+Тому в цьому прикладі ми використовуємо параметр `response_model`, а не анотацію типу повернення.
+
+...але читайте далі, щоб дізнатися, як обійти це обмеження.
+
+## Тип повернення і фільтрація даних
+
+Продовжимо з попереднього прикладу. Ми хотіли **анотувати функцію одним типом**, але при цьому повертати з неї більше даних.
+
+Ми хочемо, щоб FastAPI продовжував **фільтрувати** ці дані за допомогою response_model. Тобто навіть якщо функція повертає більше інформації, у відповіді будуть лише ті поля, які вказані у response_model.
+
+У попередньому прикладі, оскільки класи були різні, нам довелося використовувати параметр `response_model`. Але це означає, що ми не отримуємо підтримки з боку редактора коду та інструментів перевірки типів щодо типу, який повертає функція.
+
+Проте в більшості випадків, коли нам потрібно зробити щось подібне, ми просто хочемо, щоб модель **відфільтрувала або прибрала** частину даних, як у цьому прикладі.
+
+У таких випадках ми можемо використати класи та спадкування, щоб скористатися **анотаціями типів** функцій — це дає кращу підтримку з боку редактора та інструментів типу mypy, і при цьому FastAPI продовжує виконувати **фільтрацію даних** у відповіді.
+
+{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *}
+
+Завдяки цьому ми отримуємо підтримку інструментів — від редакторів і mypy, оскільки цей код є коректним з точки зору типів, — але ми також отримуємо фільтрацію даних від FastAPI.
+
+Як це працює? Давайте розберемося. 🤓
+
+### Типи та підтримка інструментів
+
+Спершу подивимось, як це бачать редактори, mypy та інші інструменти.
+
+`BaseUser` має базові поля. Потім `UserIn` успадковує `BaseUser` і додає поле `password`, отже, він матиме всі поля з обох моделей.
+
+Ми зазначаємо тип повернення функції як `BaseUser`, але фактично повертаємо екземпляр `UserIn`.
+
+Редактор, mypy та інші інструменти не скаржитимуться на це, тому що з точки зору типізації `UserIn` є підкласом `BaseUser`, а це означає, що він є `валідним` типом, коли очікується будь-що, що є `BaseUser`.
+
+### Фільтрація даних у FastAPI
+
+Тепер для FastAPI він бачить тип повернення і переконується, що те, що Ви повертаєте, містить **тільки** поля, які оголошені у цьому типі.
+
+FastAPI виконує кілька внутрішніх операцій з Pydantic, щоб гарантувати, що правила наслідування класів не застосовуються для фільтрації повернених даних, інакше Ви могли б повернути значно більше даних, ніж очікували.
+
+Таким чином, Ви отримуєте найкраще з двох світів: анотації типів **з підтримкою інструментів** і **фільтрацію даних**.
+
+## Подивитись у документації
+
+Коли Ви дивитесь автоматичну документацію, Ви можете побачити, що вхідна модель і вихідна модель мають власну JSON-схему:
+
+

+
+І обидві моделі використовуються для інтерактивної API-документації:
+
+

+
+## Інші анотації типів повернення
+
+Існують випадки, коли Ви повертаєте щось, що не є допустимим полем Pydantic, але анотуєте це у функції лише для того, щоб отримати підтримку від інструментів (редактора, mypy тощо).
+
+### Повернення Response напряму
+
+Найпоширенішим випадком буде [повернення Response напряму, як пояснюється пізніше у розширеній документації](../advanced/response-directly.md){.internal-link target=_blank}.
+
+{* ../../docs_src/response_model/tutorial003_02.py hl[8,10:11] *}
+
+Цей простий випадок автоматично обробляється FastAPI, тому що анотація типу повернення — це клас (або підклас) `Response`.
+
+І інструменти також будуть задоволені, бо і `RedirectResponse`, і `JSONResponse` є підкласами `Response`, отже анотація типу коректна.
+
+### Анотація підкласу Response
+
+Також можна використовувати підклас `Response` у анотації типу:
+
+{* ../../docs_src/response_model/tutorial003_03.py hl[8:9] *}
+
+Це теж працюватиме, бо `RedirectResponse` — підклас `Response`, і FastAPI автоматично обробить цей простий випадок.
+
+### Некоректні анотації типу повернення
+
+Але коли Ви повертаєте якийсь інший довільний об’єкт, що не є валідним типом Pydantic (наприклад, об’єкт бази даних), і анотуєте його так у функції, FastAPI спробує створити Pydantic модель відповіді на основі цієї анотації типу, і це завершиться помилкою.
+
+Те саме станеться, якщо Ви використовуєте
union між різними типами, де один або більше не є валідними типами Pydantic, наприклад, це спричинить помилку 💥:
+
+{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *}
+
+...це не працює, тому що тип анотації не є типом Pydantic і не є просто класом `Response` або його підкласом, а є об’єднанням (union) — або `Response`, або `dict`.
+
+### Відключення Моделі Відповіді
+
+Продовжуючи приклад вище, можливо, Ви не хочете використовувати стандартну валідацію даних, автоматичну документацію, фільтрацію тощо, які FastAPI виконує за замовчуванням.
+
+Але ви все одно можете залишити анотацію типу у функції, щоб зберегти підтримку з боку інструментів, таких як редактори коду або статичні перевірки типів (наприклад, mypy).
+
+У такому випадку ви можете вимкнути генерацію моделі відповіді, встановивши `response_model=None`:
+
+{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *}
+
+Це змусить FastAPI пропустити генерацію моделі відповіді, і таким чином Ви зможете використовувати будь-які анотації типів повернення без впливу на вашу FastAPI аплікацію. 🤓
+
+## Параметри кодування моделі відповіді
+
+Ваша модель відповіді може мати значення за замовчуванням, наприклад:
+
+{* ../../docs_src/response_model/tutorial004_py310.py hl[9,11:12] *}
+
+* `description: Union[str, None] = None` (або `str | None = None` у Python 3.10) має значення за замовчуванням `None`.
+* `tax: float = 10.5` має значення за замовчуванням `10.5`.
+* `tags: List[str] = []` має значення за замовчуванням порожній список: `[]`.
+
+Але Ви можете захотіти не включати їх у результат, якщо вони фактично не були збережені.
+
+Наприклад, якщо у Вас є моделі з багатьма необов’язковими атрибутами у NoSQL базі даних, але Ви не хочете відправляти дуже довгі JSON-відповіді, повні значень за замовчуванням.
+
+### Використовуйте параметр `response_model_exclude_unset`
+
+Ви можете встановити параметр декоратора шляху `response_model_exclude_unset=True`:
+
+{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *}
+
+і ці значення за замовчуванням не будуть включені у відповідь, тільки фактично встановлені значення.
+
+Отже, якщо Ви надішлете запит до цього оператора шляху для елемента з item_id `foo`, відповідь (без включення значень за замовчуванням) буде:
+
+```JSON
+{
+ "name": "Foo",
+ "price": 50.2
+}
+```
+
+/// info | Інформація
+
+У Pydantic версії 1 метод називався `.dict()`, він був застарілий (але ще підтримується) у Pydantic версії 2 і перейменований у `.model_dump()`.
+
+Приклади тут використовують `.dict()` для сумісності з Pydantic v1, але Вам слід використовувати `.model_dump()`, якщо Ви можете використовувати Pydantic v2.
+
+///
+
+/// info | Інформація
+
+FastAPI використовує `.dict()` моделі Pydantic з
параметром `exclude_unset`, щоб досягти цього.
+
+///
+
+/// info | Інформація
+
+Ви також можете використовувати:
+
+* `response_model_exclude_defaults=True`
+* `response_model_exclude_none=True`
+
+як описано в
документації Pydantic for `exclude_defaults` та `exclude_none`.
+
+///
+
+#### Дані зі значеннями для полів із типовими значеннями
+
+Але якщо Ваші дані мають значення для полів моделі з типовими значеннями, як у елемента з item_id `bar`:
+
+```Python hl_lines="3 5"
+{
+ "name": "Bar",
+ "description": "The bartenders",
+ "price": 62,
+ "tax": 20.2
+}
+```
+вони будуть включені у відповідь.
+
+#### Дані з тими самими значеннями, що й типові
+
+Якщо дані мають ті самі значення, що й типові, як у елемента з item_id `baz`:
+
+```Python hl_lines="3 5-6"
+{
+ "name": "Baz",
+ "description": None,
+ "price": 50.2,
+ "tax": 10.5,
+ "tags": []
+}
+```
+
+FastAPI достатньо розумний (насправді, Pydantic достатньо розумний), щоб зрозуміти, що, хоча `description`, `tax` і `tags` мають ті самі значення, що й типові, вони були встановлені явно (а не взяті як значення за замовчуванням).
+
+Отже, вони будуть включені у JSON-відповідь.
+
+/// tip | Порада
+
+Зверніть увагу, що типові значення можуть бути будь-якими, не лише `None`.
+
+Це може бути list (`[]`), `float` 10.5 тощо.
+
+///
+
+### `response_model_include` та `response_model_exclude`
+
+Ви також можете використовувати параметри *декоратора операції шляху* `response_model_include` та `response_model_exclude`.
+
+Вони приймають `set` (множину) рядків (`str`) з іменами атрибутів, які потрібно включити (пропускаючи інші) або виключити (включаючи інші).
+
+Це можна використовувати як швидкий спосіб, якщо у Вас є лише одна модель Pydantic і Ви хочете видалити деякі дані з виводу.
+
+/// tip | Порада
+
+Але все ж рекомендується використовувати описані вище підходи, із застосуванням кількох класів, замість цих параметрів.
+
+
+Це тому, що JSON Schema, який генерується у вашому OpenAPI додатку (і в документації), все одно буде відповідати повній моделі, навіть якщо Ви використовуєте `response_model_include` або `response_model_exclude` для виключення деяких атрибутів.
+
+Це також стосується `response_model_by_alias`, який працює подібним чином.
+
+///
+
+{* ../../docs_src/response_model/tutorial005_py310.py hl[29,35] *}
+
+/// tip | Порада
+
+Синтаксис `{"name", "description"}` створює `set` з цими двома значеннями.
+
+Він еквівалентний `set(["name", "description"])`.
+
+///
+
+#### Використання `list` замість `set`
+
+Якщо Ви забудете використати `set` і натомість застосуєте `list` або `tuple`, FastAPI все одно перетворить це на `set`, і все працюватиме правильно:
+
+{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *}
+
+## Підсумок
+
+Використовуйте параметр `response_model` *декоратора операції шляху*, щоб визначати моделі відповіді, особливо щоб гарантувати фільтрацію приватних даних.
+
+Використовуйте `response_model_exclude_unset`, щоб повертати лише явно встановлені значення.
diff --git a/docs/uk/docs/tutorial/response-status-code.md b/docs/uk/docs/tutorial/response-status-code.md
new file mode 100644
index 000000000..1ed69d6f2
--- /dev/null
+++ b/docs/uk/docs/tutorial/response-status-code.md
@@ -0,0 +1,100 @@
+# Статус коди Відповідей
+
+Так само як Ви можете вказати модель відповіді, Ви також можете оголосити HTTP код статусу для відповіді за допомогою параметра `status_code` в будь-якій з *операцій шляху*:
+
+* `@app.get()`
+* `@app.post()`
+* `@app.put()`
+* `@app.delete()`
+* тощо.
+
+{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
+
+/// note | Нотатка
+
+Зверніть увагу, що `status_code` є параметром методу "декоратора" (`get`, `post` і т.д.), а не Вашої *функції операції шляху*, як усі інші параметри та тіло запиту.
+
+///
+
+Параметр `status_code` приймає число, яке відповідає HTTP коду статусу.
+
+/// info | Інформація
+`status_code` також може отримувати значення з `IntEnum`, наприклад, з Python
`http.HTTPStatus`.
+
+///
+
+Він буде:
+
+* Повертати вказаний код статусу у відповіді.
+* Документувати його як такий у схемі OpenAPI (і, таким чином, в інтерфейсі користувача):
+
+

+
+/// note | Нотатка
+
+Деякі коди відповіді (див. наступний розділ) вказують, що відповідь не має тіла.
+
+FastAPI знає про це і створить OpenAPI документацію, яка вказує, що тіла відповіді немає.
+
+///
+
+## Про HTTP статус коди
+
+/// note | Нотатка
+
+Якщо Ви вже знаєте, що таке HTTP коди статусу, переходьте до наступного розділу.
+
+///
+
+В HTTP Ви надсилаєте числовий код статусу з 3 цифр як частину відповіді.
+
+Ці коди статусу мають пов’язану назву для їх розпізнавання, але найважливішою частиною є саме число.
+
+Коротко:
+
+* **`100 - 199`** "Інформаційні" відповіді. Ви рідко використовуєте їх напряму. Відповіді з такими кодами не можуть мати тіла.
+* **`200 - 299`** "Успішні" відповіді. Це ті, які Ви використовуватимете найчастіше.
+ * `200` - код за замовчуванням, який означає, що все пройшло "OK".
+ * Інший приклад – `201`, "Created" (створено). Його зазвичай використовують після створення нового запису в базі даних.
+ * Особливий випадок – `204`, "No Content" (немає вмісту). Ця відповідь використовується, коли немає даних для повернення клієнту, тому відповідь не повинна мати тіла.
+* **`300 - 399`** "Перенаправлення". Відповіді з цими кодами можуть мати або не мати тіла, за винятком `304`, "Not Modified" (не змінено), яка не повинна мати тіла.
+* **`400 - 499`** "Помилка клієнта". Це другий тип, який Ви, ймовірно, будете використовувати найчастіше.
+ * Приклад `404`, "Not Found" (не знайдено).
+ * Для загальних помилок клієнта можна використовувати `400`.
+* `500 - 599` "Помилки сервера". Ви майже ніколи не використовуєте їх напряму. Якщо в коді Вашого застосунку або на сервері щось пішло не так, автоматично буде повернено один із цих кодів статусу.
+
+/// tip | Порада
+
+Щоб дізнатися більше про кожен код статусу і призначення кожного з них, перегляньте документацію
MDN про HTTP коди статусу.
+
+///
+
+## Легкий спосіб запам'ятати назви
+
+Розглянемо ще раз попередній приклад:
+
+{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
+
+`201` - це код статусу для "Created" (створено).
+
+Але Вам не потрібно запам'ятовувати, що означає кожен із цих кодів.
+
+Ви можете використовувати зручні змінні з `fastapi.status`
+
+{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *}
+
+Ці змінні просто для зручності. Вони містять ті ж самі числа, але Ви можете скористатися автозаповненням в редакторі:
+
+

+
+/// note | Технічні деталі
+
+Ви також можете використати `from starlette import status`.
+
+**FastAPI** надає ті ж самі змінні `starlette.status` як `fastapi.status`, просто для зручності розробника. Однак вони походять безпосередньо зі Starlette.
+
+///
+
+## Зміна значення за замовчуванням
+
+Далі, у Посібнику для досвідчених користувачів{.internal-link target=_blank}, Ви дізнаєтесь, як повернути інший код статусу, ніж той, який Ви оголосили тут.
diff --git a/docs/uk/docs/tutorial/schema-extra-example.md b/docs/uk/docs/tutorial/schema-extra-example.md
new file mode 100644
index 000000000..853fd5e65
--- /dev/null
+++ b/docs/uk/docs/tutorial/schema-extra-example.md
@@ -0,0 +1,222 @@
+# Декларування прикладів вхідних даних
+
+Ви можете задати приклади даних, які Ваш застосунок може отримувати.
+
+Ось кілька способів, як це зробити.
+
+## Додаткові дані JSON-схеми в моделях Pydantic
+
+Ви можете задати `examples` для моделі Pydantic, які буде додано до згенерованої JSON-схеми.
+
+//// tab | Pydantic v2
+
+{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *}
+
+////
+
+//// tab | Pydantic v1
+
+{* ../../docs_src/schema_extra_example/tutorial001_pv1_py310.py hl[13:23] *}
+
+////
+
+Ця додаткова інформація буде додана як є до **JSON-схеми**, і вона буде використовуватися в документації до API.
+
+//// tab | Pydantic v2
+
+У версії Pydantic 2 використовується атрибут `model_config`, який приймає `dict`, як описано в
документації Pydantic: Конфігурація.
+
+Ви можете встановити `"json_schema_extra"` як `dict`, що містить будь-які додаткові дані, які Ви хочете відобразити у згенерованій JSON-схемі, включаючи `examples`.
+
+////
+
+//// tab | Pydantic v1
+
+У версії Pydantic 1 використовується внутрішній клас `Config` і параметр `schema_extra`, як описано в
документації Pydantic: Налаштування схеми.
+
+Ви можете задати `schema_extra` як `dict`, що містить будь-які додаткові дані, які Ви хочете бачити у згенерованій JSON-схемі, включаючи `examples`.
+
+////
+
+/// tip | Підказка
+
+Ви можете використати ту ж техніку, щоб розширити JSON-схему і додати власну додаткову інформацію.
+
+Наприклад, Ви можете використати її для додавання метаданих для інтерфейсу користувача на фронтенді тощо.
+
+///
+
+/// info | Інформація
+
+OpenAPI 3.1.0 (який використовується починаючи з FastAPI 0.99.0) додав підтримку `examples`, що є частиною стандарту **JSON-схеми**.
+
+До цього підтримувався лише ключ `example` з одним прикладом. Він все ще підтримується в OpenAPI 3.1.0, але є застарілим і не входить до стандарту JSON Schema. Тому рекомендується перейти з `example` на `examples`. 🤓
+
+Більше про це можна прочитати в кінці цієї сторінки.
+
+///
+
+## Додаткові аргументи `Field`
+
+Коли ви використовуєте `Field()` у моделях Pydantic, Ви також можете вказати додаткові `examples`:
+
+{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *}
+
+## `examples` у JSON-схемі — OpenAPI
+
+При використанні будь-кого з наступного:
+
+* `Path()`
+* `Query()`
+* `Header()`
+* `Cookie()`
+* `Body()`
+* `Form()`
+* `File()`
+
+Ви також можете задати набір `examples` з додатковою інформацією, яка буде додана до їхніх **JSON-схем** у **OpenAPI**.
+
+### `Body` з `examples`
+
+Тут ми передаємо `examples`, які містять один приклад очікуваних даних у `Body()`:
+
+{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *}
+
+### Приклад у UI документації
+
+За допомогою будь-якого з наведених вище методів це виглядатиме так у документації за `/docs`:
+
+

+
+### `Body` з кількома `examples`
+
+Звичайно, Ви також можете передати кілька `examples`:
+
+{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *}
+
+Коли Ви це робите, приклади будуть частиною внутрішньої **JSON-схеми** для цих даних.
+
+Втім, на момент написання цього (
26 серпня 2023), Swagger UI — інструмент, який відповідає за відображення UI документації — не підтримує показ кількох прикладів у **JSON-схеми**. Але нижче можна прочитати про обхідний шлях.
+
+### Специфічні для OpenAPI `examples`
+
+Ще до того, як **JSON-схема** почала підтримувати `examples`, OpenAPI вже мала підтримку поля з такою ж назвою — `examples`.
+
+Це **специфічне для OpenAPI** поле `examples` розміщується в іншій частині специфікації OpenAPI — у **деталях кожної *операції шляху***, а не всередині самої JSON-схеми.
+
+Swagger UI вже давно підтримує це поле `examples`. Тому Ви можете використовувати його, щоб **відображати** кілька **прикладів у документації**.
+
+Це поле `examples` у специфікації OpenAPI — це `dict` (словник) з **кількома прикладами** (а не список `list`), кожен із яких може містити додаткову інформацію, що буде додана до **OpenAPI**.
+
+Воно не включається до JSON Schema кожного параметра, а розміщується зовні, безпосередньо в *операції шляху*.
+
+### Використання параметра `openapi_examples`
+
+Ви можете оголосити специфічні для OpenAPI `examples` у FastAPI за допомогою параметра `openapi_examples` для:
+
+* `Path()`
+* `Query()`
+* `Header()`
+* `Cookie()`
+* `Body()`
+* `Form()`
+* `File()`
+
+Ключі словника (`dict`) ідентифікують кожен приклад, а кожне значення `dict` — кожен специфічний словник `dict` в `examples` може містити:
+
+* `summary`: короткий опис прикладу.
+* `description`: розгорнутий опис (може містити Markdown).
+* `value`: сам приклад, наприклад, словник (`dict`).
+* `externalValue`: альтернатива `value`, URL-адреса, що вказує на приклад. Проте ця опція може не підтримуватися більшістю інструментів, на відміну від `value`.
+
+Використання виглядає так:
+
+{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *}
+
+### Приклади OpenAPI у UI документації
+
+З параметром `openapi_examples`, доданим до `Body()`, документація `/docs` виглядатиме так:
+
+

+
+## Технічні деталі
+
+/// tip | Підказка
+
+Якщо Ви вже використовуєте **FastAPI** версії **0.99.0 або вище**, Ви можете **пропустити** цей розділ.
+
+Він більш актуальний для старих версій, до появи OpenAPI 3.1.0.
+
+Можна вважати це коротким **історичним екскурсом** у OpenAPI та JSON Schema. 🤓
+
+///
+
+/// warning | Попередження
+
+Це дуже технічна інформація про стандарти **JSON Schema** і **OpenAPI**.
+
+Якщо вищезгадані ідеї вже працюють у Вас — можете не заглиблюватися в ці деталі.
+
+///
+
+До OpenAPI 3.1.0 специфікація використовувала стару та модифіковану версію **JSON Schema**.
+
+Оскільки JSON Schema раніше не підтримувала `examples`, OpenAPI додала власне поле `examples`.
+
+OpenAPI також додала `example` і `examples` до інших частин специфікації:
+
+*
`Parameter Object` (в специфікації) використовується FastAPI для:
+ * `Path()`
+ * `Query()`
+ * `Header()`
+ * `Cookie()`
+*
`Request Body Object`, в полі `content`, в `Media Type Object` (в специфікації) використовується FastAPI для:
+ * `Body()`
+ * `File()`
+ * `Form()`
+
+/// info | Інформація
+
+Цей старий параметр `examples`, специфічний для OpenAPI, тепер називається `openapi_examples`, починаючи з FastAPI версії `0.103.0`.
+
+///
+
+### Поле `examples` у JSON Schema
+
+Пізніше JSON Schema додала поле
`examples` у нову версію специфікації.
+
+І вже OpenAPI 3.1.0 базується на цій новій версії (JSON Schema 2020-12), яка включає поле `examples`.
+
+Тепер це поле `examples` є пріоритетним і замінює старе (і кастомне) поле `example`, яке стало застарілим.
+
+Нове поле `examples` у JSON Schema — це **просто список (`list`)** прикладів, без додаткових метаданих (на відміну від OpenAPI).
+
+/// info | Інформація
+
+Навіть після того, як з'явився OpenAPI 3.1.0, який підтримував examples у JSON Schema, інструмент Swagger UI ще деякий час не підтримував цю версію (підтримка з’явилась з версії 5.0.0 🎉).
+
+Через це версії FastAPI до 0.99.0 все ще використовували версії OpenAPI нижчі за 3.1.0.
+
+///
+
+### `Examples` в Pydantic і FastAPI
+
+Коли Ви додаєте `examples` у модель Pydantic через `schema_extra` або `Field(examples=["something"])`, ці приклади додаються до **JSON Schema** цієї моделі.
+
+І ця **JSON Schema** Pydantic-моделі включається до **OpenAPI** Вашого API, а потім використовується в UI документації (docs UI).
+
+У версіях FastAPI до 0.99.0 (починаючи з 0.99.0 використовується новіший OpenAPI 3.1.0), коли Ви використовували `example` або `examples` з іншими утилітами (`Query()`, `Body()` тощо), ці приклади не додавалися до JSON Schema, який описує ці дані (навіть не до власної версії JSON Schema у OpenAPI). Натомість вони додавалися безпосередньо до опису *обробника шляху* *(path operation)* в OpenAPI (тобто поза межами частин, які використовують JSON Schema).
+
+Але тепер, коли FastAPI 0.99.0 і вище використовують OpenAPI 3.1.0, а той — JSON Schema 2020-12, разом із Swagger UI 5.0.0 і вище — все стало більш узгодженим, і examples тепер включаються до JSON Schema.
+
+### Swagger UI та специфічні для OpenAPI `examples`
+
+Раніше (станом на 26 серпня 2023 року) Swagger UI не підтримував кілька прикладів у JSON Schema, тому користувачі не мали можливості показати декілька прикладів у документації.
+
+Щоб вирішити це, FastAPI починаючи з версії 0.103.0 **додав підтримку** старого **OpenAPI-специфічного** поля `examples` через новий параметр `openapi_examples`. 🤓
+
+### Підсумок
+
+Раніше я казав, що не люблю історію... а тепер ось я — розповідаю "технічні історичні" лекції. 😅
+
+Коротко: **оновіться до FastAPI 0.99.0 або вище** — і все стане значно **простішим, узгодженим та інтуїтивно зрозумілим**, і Вам не доведеться знати всі ці історичні деталі. 😎
diff --git a/docs/uk/docs/tutorial/security/index.md b/docs/uk/docs/tutorial/security/index.md
new file mode 100644
index 000000000..c3d94be8d
--- /dev/null
+++ b/docs/uk/docs/tutorial/security/index.md
@@ -0,0 +1,104 @@
+# Безпека
+
+Існує багато способів реалізувати безпеку, автентифікацію та авторизацію.
+
+Це зазвичай складна і "непроста" тема.
+
+У багатьох фреймворках і системах забезпечення безпеки та автентифікації займає величезну частину зусиль і коду (іноді — понад 50% всього написаного коду).
+
+**FastAPI** надає кілька інструментів, які допоможуть Вам впоратися з **безпекою** легко, швидко, стандартним способом, без необхідності вивчати всі специфікації безпеки.
+
+Але спочатку — кілька коротких понять.
+
+## Поспішаєте?
+
+Якщо Вам не цікаві всі ці терміни й просто потрібно *швидко* додати автентифікацію за логіном і паролем — переходьте до наступних розділів.
+
+## OAuth2
+
+OAuth2 — це специфікація, що описує кілька способів обробки автентифікації та авторизації.
+
+Це досить об'ємна специфікація, яка охоплює складні випадки використання.
+
+Вона включає способи автентифікації через "третю сторону".
+
+Саме це лежить в основі "входу через Google, Facebook, X (Twitter), GitHub" тощо.
+
+### OAuth 1
+
+Раніше існував OAuth 1, який значно відрізняється від OAuth2 і є складнішим, оскільки містив специфікації для шифрування комунікацій.
+
+Зараз майже не використовується.
+
+OAuth2 не вказує, як саме шифрувати з'єднання — воно очікує, що ваш застосунок працює через HTTPS.
+
+/// tip | Порада
+
+У розділі про **деплой** Ви побачите, як налаштувати HTTPS безкоштовно з Traefik та Let's Encrypt.
+
+///
+
+## OpenID Connect
+
+OpenID Connect — ще одна специфікація, побудована на основі **OAuth2**.
+
+Вона розширює OAuth2, уточнюючи деякі неоднозначності для досягнення кращої сумісності.
+
+Наприклад, вхід через Google використовує OpenID Connect (який базується на OAuth2).
+
+Але вхід через Facebook — ні. Він має власну реалізацію на базі OAuth2.
+
+### OpenID (не "OpenID Connect")
+
+Існувала також специфікація "OpenID", яка намагалася розвʼязати ті самі задачі, що й **OpenID Connect**, але не базувалась на OAuth2.
+
+Це була зовсім інша система, і сьогодні вона майже не використовується.
+
+## OpenAPI
+
+OpenAPI (раніше Swagger) — це специфікація для побудови API (тепер під егідою Linux Foundation).
+
+**FastAPI** базується на **OpenAPI**.
+
+Завдяки цьому Ви отримуєте автоматичну інтерактивну документацію, генерацію коду та багато іншого.
+
+OpenAPI дозволяє описувати різні "схеми" безпеки.
+
+Використовуючи їх, Ви можете скористатися всіма цими інструментами, що базуються на стандартах, зокрема інтерактивними системами документації.
+
+OpenAPI визначає такі схеми безпеки:
+
+* `apiKey`: специфічний для застосунку ключ, який може передаватися через:
+ * Параметр запиту.
+ * Заголовок.
+ * Cookie.
+* `http`: стандартні методи HTTP-автентифікації, включаючи:
+ * `bearer`: заголовок `Authorization` зі значенням `Bearer` та токеном. Це успадковано з OAuth2.
+ * HTTP Basic автентифікація
+ * HTTP Digest, тощо.
+* `oauth2`: усі способи обробки безпеки за допомогою OAuth2 (так звані «потоки»).
+ * Деякі з цих потоків підходять для створення власного провайдера автентифікації OAuth 2.0 (наприклад, Google, Facebook, X (Twitter), GitHub тощо):
+ * `implicit`— неявний
+ * `clientCredentials`— облікові дані клієнта
+ * `authorizationCode` — код авторизації
+ * Але є один окремий «потік», який ідеально підходить для реалізації автентифікації всередині одного додатку:
+ * `password`: у наступних розділах буде приклад використання цього потоку.
+* `openIdConnect`: дозволяє автоматично виявляти параметри автентифікації OAuth2.
+ * Це автоматичне виявлення визначається у специфікації OpenID Connect.
+
+
+/// tip | Порада
+
+Інтеграція інших провайдерів автентифікації/авторизації, таких як Google, Facebook, X (Twitter), GitHub тощо — також можлива і відносно проста.
+
+Найскладніше — це створити власного провайдера автентифікації/авторизації, як Google чи Facebook. Але **FastAPI** надає Вам інструменти, щоб зробити це легко, беручи на себе важку частину роботи.
+
+///
+
+## Інструменти **FastAPI**
+
+FastAPI надає кілька інструментів для кожної з описаних схем безпеки в модулі `fastapi.security`, які спрощують використання цих механізмів захисту.
+
+У наступних розділах Ви побачите, як додати безпеку до свого API за допомогою цих інструментів **FastAPI**.
+
+А також побачите, як вона автоматично інтегрується в інтерактивну документацію вашого API.
diff --git a/docs/uk/docs/tutorial/static-files.md b/docs/uk/docs/tutorial/static-files.md
new file mode 100644
index 000000000..a84782d8f
--- /dev/null
+++ b/docs/uk/docs/tutorial/static-files.md
@@ -0,0 +1,40 @@
+# Статичні файли
+
+Ви можете автоматично надавати статичні файли з каталогу, використовуючи `StaticFiles`.
+
+## Використання `StaticFiles`
+
+* Імпортуйте `StaticFiles`.
+* "Під'єднати" екземпляр `StaticFiles()` з вказанням необхідного шляху.
+
+{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
+
+/// note | Технічні деталі
+
+Ви також можете використовувати `from starlette.staticfiles import StaticFiles`.
+
+**FastAPI** надає той самий `starlette.staticfiles`, що й `fastapi.staticfiles` для зручності розробників. Але фактично він безпосередньо походить із Starlette.
+
+///
+
+### Що таке "Під'єднання"
+
+"Під'єднання" означає додавання повноцінного "незалежного" застосунку за певним шляхом, який потім обробляє всі під шляхи.
+
+Це відрізняється від використання `APIRouter`, оскільки під'єднаний застосунок є повністю незалежним. OpenAPI та документація вашого основного застосунку не будуть знати нічого про ваш під'єднаний застосунок.
+
+Ви можете дізнатися більше про це в [Посібнику для просунутих користувачів](../advanced/index.md){.internal-link target=_blank}.
+
+## Деталі
+
+Перше `"/static"` вказує на під шлях, за яким буде "під'єднано" цей новий "застосунок". Тому будь-який шлях, який починається з `"/static"`, буде оброблятися ним.
+
+`directory="static"` визначає каталог, що містить ваші статичні файли.
+
+`name="static"` це ім'я, яке можна використовувати всередині **FastAPI**.
+
+Усі ці параметри можуть бути змінені відповідно до потреб і особливостей вашого застосунку.
+
+## Додаткова інформація
+
+Детальніше про налаштування та можливості можна дізнатися в
документації Starlette про статичні файли.
diff --git a/docs/uk/docs/tutorial/testing.md b/docs/uk/docs/tutorial/testing.md
new file mode 100644
index 000000000..25fc370d6
--- /dev/null
+++ b/docs/uk/docs/tutorial/testing.md
@@ -0,0 +1,240 @@
+# Тестування
+
+Тестування **FastAPI** додатків є простим та ефективним завдяки бібліотеці
Starlette, яка базується на
HTTPX.
+Оскільки HTTPX розроблений на основі Requests, його API є інтуїтивно зрозумілим для тих, хто вже знайомий з Requests.
+
+З його допомогою Ви можете використовувати
pytest безпосередньо з **FastAPI**.
+
+## Використання `TestClient`
+
+/// info | Інформація
+
+Щоб використовувати `TestClient`, спочатку встановіть
`httpx`.
+
+Переконайтеся, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили саму бібліотеку, наприклад:
+
+```console
+$ pip install httpx
+```
+
+///
+
+Імпортуйте `TestClient`.
+
+Створіть `TestClient`, передавши йому Ваш застосунок **FastAPI**.
+
+Створюйте функції з іменами, що починаються з `test_` (це стандартна угода для `pytest`).
+
+Використовуйте об'єкт `TestClient` так само як і `httpx`.
+
+Записуйте прості `assert`-вирази зі стандартними виразами Python, які потрібно перевірити (це також стандарт для `pytest`).
+
+{* ../../docs_src/app_testing/tutorial001.py hl[2,12,15:18] *}
+
+
+/// tip | Порада
+
+Зверніть увагу, що тестові функції — це звичайні `def`, а не `async def`.
+
+Виклики клієнта також звичайні, без використання `await`.
+
+Це дозволяє використовувати `pytest` без зайвих ускладнень.
+
+///
+
+/// note | Технічні деталі
+
+Ви також можете використовувати `from starlette.testclient import TestClient`.
+
+**FastAPI** надає той самий `starlette.testclient` під назвою `fastapi.testclient` для зручності розробників, але він безпосередньо походить із Starlette.
+
+///
+
+/// tip | Порада
+
+Якщо Вам потрібно викликати `async`-функції у ваших тестах, окрім відправлення запитів до FastAPI-застосунку (наприклад, асинхронні функції роботи з базою даних), перегляньте [Асинхронні тести](../advanced/async-tests.md){.internal-link target=_blank} у розширеному керівництві.
+
+///
+
+## Розділення тестів
+
+У реальному застосунку Ваші тести, ймовірно, будуть в окремому файлі.
+
+Також Ваш **FastAPI**-застосунок може складатися з кількох файлів або модулів тощо.
+
+### Файл застосунку **FastAPI**
+
+Припустимо, у Вас є структура файлів, описана в розділі [Більші застосунки](bigger-applications.md){.internal-link target=_blank}:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ └── main.py
+```
+У файлі `main.py` знаходиться Ваш застосунок **FastAPI** :
+
+{* ../../docs_src/app_testing/main.py *}
+
+### Файл тестування
+
+Ви можете створити файл `test_main.py` з Вашими тестами. Він може знаходитися в тому ж пакеті Python (у тій самій директорії з файлом `__init__.py`):
+
+
+``` hl_lines="5"
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+│ └── test_main.py
+```
+
+Оскільки цей файл знаходиться в тому ж пакеті, Ви можете використовувати відносний імпорт, щоб імпортувати об'єкт `app` із модуля `main` (`main.py`):
+
+{* ../../docs_src/app_testing/test_main.py hl[3] *}
+
+
+...і написати код для тестів так само як і раніше.
+
+## Тестування: розширений приклад
+
+Тепер розширимо цей приклад і додамо більше деталей, щоб побачити, як тестувати різні частини.
+
+### Розширений файл застосунку **FastAPI**
+
+Залишимо ту саму структуру файлів:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+│ └── test_main.py
+```
+
+Припустимо, що тепер файл `main.py` із Вашим **FastAPI**-застосунком містить додаткові операції шляху (**path operations**).
+
+Він має `GET`-операцію, яка може повертати помилку.
+
+Він має `POST`-операцію, яка може повертати кілька помилок.
+
+Обидві операції шляху вимагають заголовок `X-Token`.
+
+//// tab | Python 3.10+
+
+```Python
+{!> ../../docs_src/app_testing/app_b_an_py310/main.py!}
+```
+
+////
+
+//// tab | Python 3.9+
+
+```Python
+{!> ../../docs_src/app_testing/app_b_an_py39/main.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python
+{!> ../../docs_src/app_testing/app_b_an/main.py!}
+```
+
+////
+
+//// tab | Python 3.10+ non-Annotated
+
+/// tip | Порада
+
+Бажано використовувати версію з `Annotated`, якщо це можливо
+
+///
+
+```Python
+{!> ../../docs_src/app_testing/app_b_py310/main.py!}
+```
+
+////
+
+//// tab | Python 3.8+ non-Annotated
+
+/// tip | Порада
+
+Бажано використовувати версію з `Annotated`, якщо це можливо
+
+///
+
+```Python
+{!> ../../docs_src/app_testing/app_b/main.py!}
+```
+
+////
+
+### Розширений тестовий файл
+
+Потім Ви можете оновити `test_main.py`, додавши розширені тести:
+
+{* ../../docs_src/app_testing/app_b/test_main.py *}
+
+Коли Вам потрібно передати клієнту інформацію в запиті, але Ви не знаєте, як це зробити, Ви можете пошукати (наприклад, у Google) спосіб реалізації в `httpx`, або навіть у `requests`, оскільки HTTPX розроблений на основі дизайну Requests.
+
+Далі Ви просто повторюєте ці ж дії у ваших тестах.
+
+Наприклад:
+
+* Щоб передати *path* або *query* параметр, додайте його безпосередньо до URL.
+* Щоб передати тіло JSON, передайте Python-об'єкт (наприклад, `dict`) у параметр `json`.
+* Якщо потрібно надіслати *Form Data* замість JSON, використовуйте параметр `data`.
+* Щоб передати заголовки *headers*, використовуйте `dict` у параметрі `headers`.
+* Для *cookies* використовуйте `dict` у параметрі `cookies`.
+
+Докладніше про передачу даних у бекенд (за допомогою `httpx` або `TestClient`) можна знайти в
документації HTTPX.
+
+/// info | Інформація
+
+Зверніть увагу, що `TestClient` отримує дані, які можна конвертувати в JSON, а не Pydantic-моделі.
+Якщо у Вас є Pydantic-модель у тесті, і Ви хочете передати її дані в додаток під час тестування, Ви можете використати `jsonable_encoder`, описаний у розділі [JSON Compatible Encoder](encoder.md){.internal-link target=_blank}.
+
+///
+
+## Запуск тестів
+
+Після цього вам потрібно встановити `pytest`.
+
+Переконайтеся, що Ви створили [віртуальне середовище]{.internal-link target=_blank}, активували його і встановили необхідні пакети, наприклад:
+
+
+
+```console
+$ pip install pytest
+
+---> 100%
+```
+
+
+
+`pytest` автоматично знайде файли з тестами, виконає їх і надасть вам результати.
+
+Запустіть тести за допомогою:
+
+
+
+```console
+$ pytest
+
+================ test session starts ================
+platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
+rootdir: /home/user/code/superawesome-cli/app
+plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1
+collected 6 items
+
+---> 100%
+
+test_main.py ...... [100%]
+
+================= 1 passed in 0.03s =================
+```
+
+
diff --git a/docs/uk/mkdocs.yml b/docs/uk/mkdocs.yml
index 7f5785e3e..de18856f4 100644
--- a/docs/uk/mkdocs.yml
+++ b/docs/uk/mkdocs.yml
@@ -1,128 +1 @@
-site_name: FastAPI
-site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
-site_url: https://fastapi.tiangolo.com/uk/
-theme:
- name: material
- custom_dir: overrides
- palette:
- - scheme: default
- primary: teal
- accent: amber
- toggle:
- icon: material/lightbulb
- name: Switch to light mode
- - scheme: slate
- primary: teal
- accent: amber
- toggle:
- icon: material/lightbulb-outline
- name: Switch to dark mode
- features:
- - search.suggest
- - search.highlight
- - content.tabs.link
- icon:
- repo: fontawesome/brands/github-alt
- logo: https://fastapi.tiangolo.com/img/icon-white.svg
- favicon: https://fastapi.tiangolo.com/img/favicon.png
- language: uk
-repo_name: tiangolo/fastapi
-repo_url: https://github.com/tiangolo/fastapi
-edit_uri: ''
-google_analytics:
-- UA-133183413-1
-- auto
-plugins:
-- search
-- markdownextradata:
- data: data
-nav:
-- FastAPI: index.md
-- Languages:
- - en: /
- - az: /az/
- - de: /de/
- - es: /es/
- - fr: /fr/
- - id: /id/
- - it: /it/
- - ja: /ja/
- - ko: /ko/
- - pl: /pl/
- - pt: /pt/
- - ru: /ru/
- - sq: /sq/
- - tr: /tr/
- - uk: /uk/
- - zh: /zh/
-markdown_extensions:
-- toc:
- permalink: true
-- markdown.extensions.codehilite:
- guess_lang: false
-- mdx_include:
- base_path: docs
-- admonition
-- codehilite
-- extra
-- pymdownx.superfences:
- custom_fences:
- - name: mermaid
- class: mermaid
- format: !!python/name:pymdownx.superfences.fence_code_format ''
-- pymdownx.tabbed
-extra:
- social:
- - icon: fontawesome/brands/github-alt
- link: https://github.com/tiangolo/fastapi
- - icon: fontawesome/brands/discord
- link: https://discord.gg/VQjSZaeJmf
- - icon: fontawesome/brands/twitter
- link: https://twitter.com/fastapi
- - icon: fontawesome/brands/linkedin
- link: https://www.linkedin.com/in/tiangolo
- - icon: fontawesome/brands/dev
- link: https://dev.to/tiangolo
- - icon: fontawesome/brands/medium
- link: https://medium.com/@tiangolo
- - icon: fontawesome/solid/globe
- link: https://tiangolo.com
- alternate:
- - link: /
- name: en - English
- - link: /az/
- name: az
- - link: /de/
- name: de
- - link: /es/
- name: es - español
- - link: /fr/
- name: fr - français
- - link: /id/
- name: id
- - link: /it/
- name: it - italiano
- - link: /ja/
- name: ja - 日本語
- - link: /ko/
- name: ko - 한국어
- - link: /pl/
- name: pl
- - link: /pt/
- name: pt - português
- - link: /ru/
- name: ru - русский язык
- - link: /sq/
- name: sq - shqip
- - link: /tr/
- name: tr - Türkçe
- - link: /uk/
- name: uk - українська мова
- - link: /zh/
- name: zh - 汉语
-extra_css:
-- https://fastapi.tiangolo.com/css/termynal.css
-- https://fastapi.tiangolo.com/css/custom.css
-extra_javascript:
-- https://fastapi.tiangolo.com/js/termynal.js
-- https://fastapi.tiangolo.com/js/custom.js
+INHERIT: ../en/mkdocs.yml
diff --git a/docs/ur/docs/benchmarks.md b/docs/ur/docs/benchmarks.md
new file mode 100644
index 000000000..8d583de2f
--- /dev/null
+++ b/docs/ur/docs/benchmarks.md
@@ -0,0 +1,51 @@
+# بینچ مارکس
+انڈیپنڈنٹ ٹیک امپور بینچ مارک **FASTAPI** Uvicorn کے تحت چلنے والی ایپلی کیشنز کو
ایک تیز رفتار Python فریم ورک میں سے ایک ، صرف Starlette اور Uvicorn کے نیچے ( FASTAPI کے ذریعہ اندرونی طور پر استعمال کیا جاتا ہے ) (*)
+
+لیکن جب بینچ مارک اور موازنہ کی جانچ پڑتال کرتے ہو تو آپ کو مندرجہ ذیل بات ذہن میں رکھنی چاہئے.
+
+## بینچ مارک اور رفتار
+
+جب آپ بینچ مارک کی جانچ کرتے ہیں تو ، مساوی کے مقابلے میں مختلف اقسام کے متعدد اوزار دیکھنا عام ہے.
+
+خاص طور پر ، Uvicorn, Starlette اور FastAPI کو دیکھنے کے لئے ( بہت سے دوسرے ٹولز ) کے ساتھ موازنہ کیا گیا.
+
+ٹول کے ذریعہ حل ہونے والا آسان مسئلہ ، اس کی بہتر کارکردگی ہوگی. اور زیادہ تر بینچ مارک ٹول کے ذریعہ فراہم کردہ اضافی خصوصیات کی جانچ نہیں کرتے ہیں.
+
+درجہ بندی کی طرح ہے:
+
+
+ - سرور ASGI :Uvicorn
+
+ - Starlette: (Uvicorn استعمال کرتا ہے) ایک ویب مائیکرو فریم ورک
+
+ - FastAPI: (Starlette کا استعمال کرتا ہے) ایک API مائکرو فریم ورک جس میں APIs بنانے کے لیے کئی اضافی خصوصیات ہیں، ڈیٹا کی توثیق وغیرہ کے ساتھ۔
+
+
+
+
+
+ - Uvicorn:
+
+ - بہترین کارکردگی ہوگی، کیونکہ اس میں سرور کے علاوہ زیادہ اضافی کوڈ نہیں ہے۔
+ - آپ براہ راست Uvicorn میں درخواست نہیں لکھیں گے۔ اس کا مطلب یہ ہوگا کہ آپ کے کوڈ میں کم و بیش، کم از کم، Starlette (یا FastAPI) کی طرف سے فراہم کردہ تمام کوڈ شامل کرنا ہوں گے۔ اور اگر آپ نے ایسا کیا تو، آپ کی حتمی ایپلیکیشن کا وہی اوور ہیڈ ہوگا جیسا کہ ایک فریم ورک استعمال کرنے اور آپ کے ایپ کوڈ اور کیڑے کو کم سے کم کرنا۔
+ - اگر آپ Uvicorn کا موازنہ کر رہے ہیں تو اس کا موازنہ Daphne، Hypercorn، uWSGI وغیرہ ایپلیکیشن سرورز سے کریں۔
+
+
+
+ - Starlette:
+
+ - Uvicorn کے بعد اگلی بہترین کارکردگی ہوگی۔ درحقیقت، Starlette چلانے کے لیے Uvicorn کا استعمال کرتی ہے۔ لہذا، یہ شاید زیادہ کوڈ پر عمل درآمد کرکے Uvicorn سے "سست" ہوسکتا ہے۔
+ - لیکن یہ آپ کو آسان ویب ایپلیکیشنز بنانے کے لیے ٹولز فراہم کرتا ہے، راستوں پر مبنی روٹنگ کے ساتھ، وغیرہ۔>
+ - اگر آپ سٹارلیٹ کا موازنہ کر رہے ہیں تو اس کا موازنہ Sanic، Flask، Django وغیرہ سے کریں۔ ویب فریم ورکس (یا مائیکرو فریم ورکس)
+
+
+
+ - FastAPI:
+
+ - جس طرح سے Uvicorn Starlette کا استعمال کرتا ہے اور اس سے تیز نہیں ہو سکتا، Starlette FastAPI کا استعمال کرتا ہے، اس لیے یہ اس سے تیز نہیں ہو سکتا۔
+ - Starlette FastAPI کے اوپری حصے میں مزید خصوصیات فراہم کرتا ہے۔ وہ خصوصیات جن کی آپ کو APIs بناتے وقت تقریباً ہمیشہ ضرورت ہوتی ہے، جیسے ڈیٹا کی توثیق اور سیریلائزیشن۔ اور اسے استعمال کرنے سے، آپ کو خودکار دستاویزات مفت میں مل جاتی ہیں (خودکار دستاویزات چلنے والی ایپلی کیشنز میں اوور ہیڈ کو بھی شامل نہیں کرتی ہیں، یہ اسٹارٹ اپ پر تیار ہوتی ہیں)۔
+ - اگر آپ نے FastAPI کا استعمال نہیں کیا ہے اور Starlette کو براہ راست استعمال کیا ہے (یا کوئی دوسرا ٹول، جیسے Sanic، Flask، Responder، وغیرہ) آپ کو تمام ڈیٹا کی توثیق اور سیریلائزیشن کو خود نافذ کرنا ہوگا۔ لہذا، آپ کی حتمی ایپلیکیشن اب بھی وہی اوور ہیڈ ہوگی جیسا کہ اسے FastAPI کا استعمال کرتے ہوئے بنایا گیا تھا۔ اور بہت سے معاملات میں، یہ ڈیٹا کی توثیق اور سیریلائزیشن ایپلی کیشنز میں لکھے گئے کوڈ کی سب سے بڑی مقدار ہے۔
+ - لہذا، FastAPI کا استعمال کرکے آپ ترقیاتی وقت، Bugs، کوڈ کی لائنوں کی بچت کر رہے ہیں، اور شاید آپ کو وہی کارکردگی (یا بہتر) ملے گی اگر آپ اسے استعمال نہیں کرتے (جیسا کہ آپ کو یہ سب اپنے کوڈ میں لاگو کرنا ہوگا۔ )>
+ - اگر آپ FastAPI کا موازنہ کر رہے ہیں، تو اس کا موازنہ ویب ایپلیکیشن فریم ورک (یا ٹولز کے سیٹ) سے کریں جو ڈیٹا کی توثیق، سیریلائزیشن اور دستاویزات فراہم کرتا ہے، جیسے Flask-apispec، NestJS، Molten، وغیرہ۔ مربوط خودکار ڈیٹا کی توثیق، سیریلائزیشن اور دستاویزات کے ساتھ فریم ورک۔
+
+
diff --git a/docs/ur/mkdocs.yml b/docs/ur/mkdocs.yml
new file mode 100644
index 000000000..de18856f4
--- /dev/null
+++ b/docs/ur/mkdocs.yml
@@ -0,0 +1 @@
+INHERIT: ../en/mkdocs.yml
diff --git a/docs/vi/docs/deployment/cloud.md b/docs/vi/docs/deployment/cloud.md
new file mode 100644
index 000000000..9ab72769d
--- /dev/null
+++ b/docs/vi/docs/deployment/cloud.md
@@ -0,0 +1,17 @@
+# Triển khai FastAPI trên các Dịch vụ Cloud
+
+Bạn có thể sử dụng **bất kỳ nhà cung cấp dịch vụ cloud** nào để triển khai ứng dụng FastAPI của mình.
+
+Trong hầu hết các trường hợp, các nhà cung cấp dịch vụ cloud lớn đều có hướng dẫn triển khai FastAPI với họ.
+
+## Nhà cung cấp dịch vụ Cloud - Nhà tài trợ
+Một vài nhà cung cấp dịch vụ cloud ✨ [**tài trợ cho FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, điều này giúp đảm bảo sự phát triển liên tục và khỏe mạnh của FastAPI và hệ sinh thái của nó.
+
+Thêm nữa, điều này cũng thể hiện cam kết thực sự của họ đối với FastAPI và **cộng đồng người dùng** (bạn), vì họ không chỉ muốn cung cấp cho bạn một **dịch vụ tốt** mà còn muốn đảm bảo rằng bạn có một **framework tốt và bền vững**, đó chính là FastAPI. 🙇
+
+Bạn có thể thử các dịch vụ của họ và làm theo hướng dẫn của họ:
+
+*
Platform.sh
+*
Porter
+*
Coherence
+*
Render
diff --git a/docs/vi/docs/deployment/index.md b/docs/vi/docs/deployment/index.md
new file mode 100644
index 000000000..24ffdc71b
--- /dev/null
+++ b/docs/vi/docs/deployment/index.md
@@ -0,0 +1,21 @@
+# Triển khai
+
+Triển khai một ứng dụng **FastAPI** khá dễ dàng.
+
+## Triển khai là gì
+
+Triển khai một ứng dụng có nghĩa là thực hiện các bước cần thiết để làm cho nó **sẵn sàng phục vụ người dùng**.
+
+Đối với một **API web**, điều này có nghĩa là đặt nó trong một **máy chủ từ xa**, với một **chương trình máy chủ** cung cấp hiệu suất tốt, ổn định, v.v., để người dùng của bạn có thể truy cập ứng dụng của bạn một cách hiệu quả và không bị gián đoạn hoặc gặp vấn đề.
+
+Điều này trái ngược với các **giai đoạn phát triển**, trong đó bạn liên tục thay đổi mã, phá vỡ nó và sửa nó, ngừng và khởi động lại máy chủ phát triển, v.v.
+
+## Các Chiến lược Triển khai
+
+Có nhiều cách để triển khai ứng dụng của bạn tùy thuộc vào trường hợp sử dụng của bạn và các công cụ mà bạn sử dụng.
+
+Bạn có thể **triển khai một máy chủ** của riêng bạn bằng cách sử dụng một sự kết hợp các công cụ, hoặc bạn có thể sử dụng một **dịch vụ cloud** để làm một số công việc cho bạn, hoặc các tùy chọn khác.
+
+Tôi sẽ chỉ ra một số khái niệm chính cần thiết khi triển khai một ứng dụng **FastAPI** (mặc dù hầu hết nó áp dụng cho bất kỳ loại ứng dụng web nào).
+
+Bạn sẽ thấy nhiều chi tiết cần thiết và một số kỹ thuật để triển khai trong các phần tiếp theo. ✨
diff --git a/docs/vi/docs/deployment/versions.md b/docs/vi/docs/deployment/versions.md
new file mode 100644
index 000000000..04de393e7
--- /dev/null
+++ b/docs/vi/docs/deployment/versions.md
@@ -0,0 +1,93 @@
+# Về các phiên bản của FastAPI
+
+**FastAPI** đã được sử dụng ở quy mô thực tế (production) trong nhiều ứng dụng và hệ thống. Và phạm vi kiểm thử được giữ ở mức 100%. Nhưng việc phát triển của nó vẫn đang diễn ra nhanh chóng.
+
+Các tính năng mới được bổ sung thường xuyên, lỗi được sửa định kỳ, và mã nguồn vẫn đang được cải thiện liên tục
+
+Đó là lí do các phiên bản hiện tại vẫn còn là 0.x.x, điều này phản ánh rằng mỗi phiên bản có thể có các thay đổi gây mất tương thích. Điều này tuân theo các quy ước về
Semantic Versioning.
+
+Bạn có thể tạo ra sản phẩm thực tế với **FastAPI** ngay bây giờ (và bạn có thể đã làm điều này trong một thời gian dài), bạn chỉ cần đảm bảo rằng bạn sử dụng một phiên bản hoạt động đúng với các đoạn mã còn lại của bạn.
+
+## Cố định phiên bản của `fastapi`
+
+Điều đầu tiên bạn nên làm là "cố định" phiên bản của **FastAPI** bạn đang sử dụng để phiên bản mới nhất mà bạn biết hoạt động đúng với ứng dụng của bạn.
+
+Ví dụ, giả sử bạn đang sử dụng phiên bản `0.112.0` trong ứng dụng của bạn.
+
+Nếu bạn sử dụng một tệp `requirements.txt` bạn có thể chỉ định phiên bản với:
+
+```txt
+fastapi[standard]==0.112.0
+```
+
+Như vậy, bạn sẽ sử dụng chính xác phiên bản `0.112.0`.
+
+Hoặc bạn cũng có thể cố định nó với:
+
+```txt
+fastapi[standard]>=0.112.0,<0.113.0
+```
+
+Như vậy, bạn sẽ sử dụng các phiên bản `0.112.0` trở lên, nhưng nhỏ hơn `0.113.0`, ví dụ, một phiên bản `0.112.2` vẫn được chấp nhận.
+
+Nếu bạn sử dụng bất kỳ công cụ nào để quản lý cài đặt của bạn, như `uv`, Poetry, Pipenv, hoặc bất kỳ công cụ nào khác, chúng đều có một cách để bạn có thể định nghĩa các phiên bản cụ thể cho các gói của bạn.
+
+## Các phiên bản có sẵn
+
+Bạn có thể xem các phiên bản có sẵn (ví dụ để kiểm tra phiên bản mới nhất) trong [Release Notes](../release-notes.md){.internal-link target=_blank}.
+
+## Về các phiên bản
+
+Theo quy ước về Semantic Versioning, bất kỳ phiên bản nào bên dưới `1.0.0` có thể thêm các thay đổi gây mất tương thích.
+
+**FastAPI** cũng theo quy ước rằng bất kỳ thay đổi phiên bản "PATCH" nào là cho các lỗi và các thay đổi không gây mất tương thích.
+
+/// tip
+
+"PATCH" là số cuối cùng, ví dụ, trong `0.2.3`, phiên bản PATCH là `3`.
+
+///
+
+Vì vậy, bạn có thể cố định đến một phiên bản như:
+
+```txt
+fastapi>=0.45.0,<0.46.0
+```
+
+Các thay đổi gây mất tương thích và các tính năng mới được thêm vào trong các phiên bản "MINOR".
+
+/// tip
+
+"MINOR" là số ở giữa, ví dụ, trong `0.2.3`, phiên bản MINOR là `2`.
+
+///
+
+## Nâng cấp các phiên bản của FastAPI
+
+Bạn nên thêm các bài kiểm tra (tests) cho ứng dụng của bạn.
+
+Với **FastAPI** điều này rất dễ dàng (nhờ vào Starlette), kiểm tra tài liệu: [Testing](../tutorial/testing.md){.internal-link target=_blank}
+
+Sau khi bạn có các bài kiểm tra, bạn có thể nâng cấp phiên bản **FastAPI** lên một phiên bản mới hơn, và đảm bảo rằng tất cả mã của bạn hoạt động đúng bằng cách chạy các bài kiểm tra của bạn.
+
+Nếu mọi thứ đang hoạt động, hoặc sau khi bạn thực hiện các thay đổi cần thiết, và tất cả các bài kiểm tra của bạn đều đi qua, thì bạn có thể cố định phiên bản của `fastapi` đến phiên bản mới hơn.
+
+## Về Starlette
+
+Bạn không nên cố định phiên bản của `starlette`.
+
+Các phiên bản khác nhau của **FastAPI** sẽ sử dụng một phiên bản Starlette mới hơn.
+
+Vì vậy, bạn có thể để **FastAPI** sử dụng phiên bản Starlette phù hợp.
+
+## Về Pydantic
+
+Pydantic bao gồm các bài kiểm tra của riêng nó cho **FastAPI**, vì vậy các phiên bản mới hơn của Pydantic (trên `1.0.0`) luôn tương thích với **FastAPI**.
+
+Bạn có thể cố định Pydantic đến bất kỳ phiên bản nào trên `1.0.0` mà bạn muốn.
+
+Ví dụ:
+
+```txt
+pydantic>=2.7.0,<3.0.0
+```
diff --git a/docs/vi/docs/environment-variables.md b/docs/vi/docs/environment-variables.md
new file mode 100644
index 000000000..dd06f8959
--- /dev/null
+++ b/docs/vi/docs/environment-variables.md
@@ -0,0 +1,300 @@
+# Biến môi trường (Environment Variables)
+
+/// tip
+
+Nếu bạn đã biết về "biến môi trường" và cách sử dụng chúng, bạn có thể bỏ qua phần này.
+
+///
+
+Một biến môi trường (còn được gọi là "**env var**") là một biến mà tồn tại **bên ngoài** đoạn mã Python, ở trong **hệ điều hành**, và có thể được đọc bởi đoạn mã Python của bạn (hoặc bởi các chương trình khác).
+
+Các biến môi trường có thể được sử dụng để xử lí **các thiết lập** của ứng dụng, như một phần của **các quá trình cài đặt** Python, v.v.
+
+## Tạo và Sử dụng các Biến Môi Trường
+
+Bạn có thể **tạo** và sử dụng các biến môi trường trong **shell (terminal)**, mà không cần sử dụng Python:
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+// Bạn có thể tạo một biến môi trường MY_NAME với
+$ export MY_NAME="Wade Wilson"
+
+// Sau đó bạn có thể sử dụng nó với các chương trình khác, như
+$ echo "Hello $MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+// Tạo một biến môi trường MY_NAME
+$ $Env:MY_NAME = "Wade Wilson"
+
+// Sử dụng nó với các chương trình khác, như là
+$ echo "Hello $Env:MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+## Đọc các Biến Môi Trường trong Python
+
+Bạn cũng có thể tạo các biến môi trường **bên ngoài** đoạn mã Python, trong terminal (hoặc bằng bất kỳ phương pháp nào khác), và sau đó **đọc chúng trong Python**.
+
+Ví dụ, bạn có một file `main.py` với:
+
+```Python hl_lines="3"
+import os
+
+name = os.getenv("MY_NAME", "World")
+print(f"Hello {name} from Python")
+```
+
+/// tip
+
+Tham số thứ hai cho
`os.getenv()` là giá trị mặc định để trả về.
+
+Nếu không được cung cấp, nó mặc định là `None`, ở đây chúng ta cung cấp `"World"` là giá trị mặc định để sử dụng.
+
+///
+
+Sau đó bạn có thể gọi chương trình Python:
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+// Ở đây chúng ta chưa cài đặt biến môi trường
+$ python main.py
+
+// Vì chúng ta chưa cài đặt biến môi trường, chúng ta nhận được giá trị mặc định
+
+Hello World from Python
+
+// Nhưng nếu chúng ta tạo một biến môi trường trước đó
+$ export MY_NAME="Wade Wilson"
+
+// Và sau đó gọi chương trình lại
+$ python main.py
+
+// Bây giờ nó có thể đọc biến môi trường
+
+Hello Wade Wilson from Python
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+// Ở đây chúng ta chưa cài đặt biến môi trường
+$ python main.py
+
+// Vì chúng ta chưa cài đặt biến môi trường, chúng ta nhận được giá trị mặc định
+
+Hello World from Python
+
+// Nhưng nếu chúng ta tạo một biến môi trường trước đó
+$ $Env:MY_NAME = "Wade Wilson"
+
+// Và sau đó gọi chương trình lại
+$ python main.py
+
+// Bây giờ nó có thể đọc biến môi trường
+
+Hello Wade Wilson from Python
+```
+
+
+
+////
+
+Vì các biến môi trường có thể được tạo bên ngoài đoạn mã Python, nhưng có thể được đọc bởi đoạn mã Python, và không cần được lưu trữ (commit vào `git`) cùng với các file khác, nên chúng thường được sử dụng để lưu các thiết lập hoặc **cấu hình**.
+
+Bạn cũng có thể tạo ra một biến môi trường dành riêng cho một **lần gọi chương trình**, chỉ có thể được sử dụng bởi chương trình đó, và chỉ trong thời gian chạy của chương trình.
+
+Để làm điều này, tạo nó ngay trước chương trình đó, trên cùng một dòng:
+
+
+
+```console
+// Tạo một biến môi trường MY_NAME cho lần gọi chương trình này
+$ MY_NAME="Wade Wilson" python main.py
+
+// Bây giờ nó có thể đọc biến môi trường
+
+Hello Wade Wilson from Python
+
+// Biến môi trường không còn tồn tại sau đó
+$ python main.py
+
+Hello World from Python
+```
+
+
+
+/// tip
+
+Bạn có thể đọc thêm về điều này tại
The Twelve-Factor App: Config.
+
+///
+
+## Các Kiểu (Types) và Kiểm tra (Validation)
+
+Các biến môi trường có thể chỉ xử lí **chuỗi ký tự**, vì chúng nằm bên ngoài đoạn mã Python và phải tương thích với các chương trình khác và phần còn lại của hệ thống (và thậm chí với các hệ điều hành khác, như Linux, Windows, macOS).
+
+Điều này có nghĩa là **bất kỳ giá trị nào** được đọc trong Python từ một biến môi trường **sẽ là một `str`**, và bất kỳ hành động chuyển đổi sang kiểu dữ liệu khác hoặc hành động kiểm tra nào cũng phải được thực hiện trong đoạn mã.
+
+Bạn sẽ học thêm về việc sử dụng biến môi trường để xử lí **các thiết lập ứng dụng** trong [Hướng dẫn nâng cao - Các thiết lập và biến môi trường](./advanced/settings.md){.internal-link target=_blank}.
+
+## Biến môi trường `PATH`
+
+Có một biến môi trường **đặc biệt** được gọi là **`PATH`** được sử dụng bởi các hệ điều hành (Linux, macOS, Windows) nhằm tìm các chương trình để thực thi.
+
+Giá trị của biến môi trường `PATH` là một chuỗi dài được tạo bởi các thư mục được phân tách bởi dấu hai chấm `:` trên Linux và macOS, và bởi dấu chấm phẩy `;` trên Windows.
+
+Ví dụ, biến môi trường `PATH` có thể có dạng như sau:
+
+//// tab | Linux, macOS
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
+```
+
+Điều này có nghĩa là hệ thống sẽ tìm kiếm các chương trình trong các thư mục:
+
+* `/usr/local/bin`
+* `/usr/bin`
+* `/bin`
+* `/usr/sbin`
+* `/sbin`
+
+////
+
+//// tab | Windows
+
+```plaintext
+C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32
+```
+
+Điều này có nghĩa là hệ thống sẽ tìm kiếm các chương trình trong các thư mục:
+
+* `C:\Program Files\Python312\Scripts`
+* `C:\Program Files\Python312`
+* `C:\Windows\System32`
+
+////
+
+Khi bạn gõ một **lệnh** trong terminal, hệ điều hành **tìm kiếm** chương trình trong **mỗi thư mục** được liệt kê trong biến môi trường `PATH`.
+
+Ví dụ, khi bạn gõ `python` trong terminal, hệ điều hành tìm kiếm một chương trình được gọi `python` trong **thư mục đầu tiên** trong danh sách đó.
+
+Nếu tìm thấy, nó sẽ **sử dụng** nó. Nếu không tìm thấy, nó sẽ tiếp tục tìm kiếm trong **các thư mục khác**.
+
+### Cài đặt Python và cập nhật biến môi trường `PATH`
+
+Khi bạn cài đặt Python, bạn có thể được hỏi nếu bạn muốn cập nhật biến môi trường `PATH`.
+
+//// tab | Linux, macOS
+
+Giả sử bạn cài đặt Python vào thư mục `/opt/custompython/bin`.
+
+Nếu bạn chọn cập nhật biến môi trường `PATH`, thì cài đặt sẽ thêm `/opt/custompython/bin` vào biến môi trường `PATH`.
+
+Nó có thể có dạng như sau:
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin
+```
+
+Như vậy, khi bạn gõ `python` trong terminal, hệ thống sẽ tìm thấy chương trình Python trong `/opt/custompython/bin` (thư mục cuối) và sử dụng nó.
+
+////
+
+//// tab | Windows
+
+Giả sử bạn cài đặt Python vào thư mục `C:\opt\custompython\bin`.
+
+Nếu bạn chọn cập nhật biến môi trường `PATH`, thì cài đặt sẽ thêm `C:\opt\custompython\bin` vào biến môi trường `PATH`.
+
+Nó có thể có dạng như sau:
+
+```plaintext
+C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin
+```
+
+Như vậy, khi bạn gõ `python` trong terminal, hệ thống sẽ tìm thấy chương trình Python trong `C:\opt\custompython\bin` (thư mục cuối) và sử dụng nó.
+
+////
+
+Vậy, nếu bạn gõ:
+
+
+
+```console
+$ python
+```
+
+
+
+//// tab | Linux, macOS
+
+Hệ thống sẽ **tìm kiếm** chương trình `python` trong `/opt/custompython/bin` và thực thi nó.
+
+Nó tương đương với việc bạn gõ:
+
+
+
+```console
+$ /opt/custompython/bin/python
+```
+
+
+
+////
+
+//// tab | Windows
+
+Hệ thống sẽ **tìm kiếm** chương trình `python` trong `C:\opt\custompython\bin\python` và thực thi nó.
+
+Nó tương đương với việc bạn gõ:
+
+
+
+```console
+$ C:\opt\custompython\bin\python
+```
+
+
+
+////
+
+Thông tin này sẽ hữu ích khi bạn học về [Môi trường ảo](virtual-environments.md){.internal-link target=_blank}.
+
+## Kết luận
+
+Với những thông tin này, bạn có thể hiểu được **các biến môi trường là gì** và **cách sử dụng chúng trong Python**.
+
+Bạn có thể đọc thêm về chúng tại
Wikipedia cho Biến môi trường.
+
+Trong nhiều trường hợp, cách các biến môi trường trở nên hữu ích và có thể áp dụng không thực sự rõ ràng ngay từ đầu, nhưng chúng sẽ liên tục xuất hiện trong rất nhiều tình huống khi bạn phát triển ứng dụng, vì vậy việc hiểu biết về chúng là hữu ích.
+
+Chẳng hạn, bạn sẽ cần những thông tin này khi bạn học về [Môi trường ảo](virtual-environments.md).
diff --git a/docs/vi/docs/fastapi-cli.md b/docs/vi/docs/fastapi-cli.md
new file mode 100644
index 000000000..d9e315ae4
--- /dev/null
+++ b/docs/vi/docs/fastapi-cli.md
@@ -0,0 +1,75 @@
+# FastAPI CLI
+
+**FastAPI CLI** là một chương trình dòng lệnh có thể được sử dụng để phục vụ ứng dụng FastAPI của bạn, quản lý dự án FastAPI của bạn và nhiều hoạt động khác.
+
+Khi bạn cài đặt FastAPI (vd với `pip install "fastapi[standard]"`), nó sẽ bao gồm một gói được gọi là `fastapi-cli`, gói này cung cấp lệnh `fastapi` trong terminal.
+
+Để chạy ứng dụng FastAPI của bạn cho quá trình phát triển (development), bạn có thể sử dụng lệnh `fastapi dev`:
+
+
+
+```console
+$ fastapi dev main.py
+
+ FastAPI Starting development server 🚀
+
+ Searching for package file structure from directories with
+ __init__.py files
+ Importing from /home/user/code/awesomeapp
+
+ module 🐍 main.py
+
+ code Importing the FastAPI app object from the module with the
+ following code:
+
+ from main import app
+
+ app Using import string: main:app
+
+ server Server started at http://127.0.0.1:8000
+ server Documentation at http://127.0.0.1:8000/docs
+
+ tip Running in development mode, for production use:
+ fastapi run
+
+ Logs:
+
+ INFO Will watch for changes in these directories:
+ ['/home/user/code/awesomeapp']
+ INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to
+ quit)
+ INFO Started reloader process [383138] using WatchFiles
+ INFO Started server process [383153]
+ INFO Waiting for application startup.
+ INFO Application startup complete.
+```
+
+
+
+Chương trình dòng lệnh `fastapi` là **FastAPI CLI**.
+
+FastAPI CLI nhận đường dẫn đến chương trình Python của bạn (vd `main.py`) và tự động phát hiện đối tượng `FastAPI` (thường được gọi là `app`), xác định quá trình nhập đúng, và sau đó chạy nó (serve).
+
+Đối với vận hành thực tế (production), bạn sẽ sử dụng `fastapi run` thay thế. 🚀
+
+Ở bên trong, **FastAPI CLI** sử dụng
Uvicorn, một server ASGI có hiệu suất cao, sẵn sàng cho vận hành thực tế (production). 😎
+
+## `fastapi dev`
+
+Chạy `fastapi dev` sẽ khởi động quá trình phát triển.
+
+Mặc định, **auto-reload** được bật, tự động tải lại server khi bạn thay đổi code của bạn. Điều này tốn nhiều tài nguyên và có thể kém ổn định hơn khi nó bị tắt. Bạn nên sử dụng nó cho quá trình phát triển. Nó cũng lắng nghe địa chỉ IP `127.0.0.1`, đó là địa chỉ IP của máy tính để tự giao tiếp với chính nó (`localhost`).
+
+## `fastapi run`
+
+Chạy `fastapi run` mặc định sẽ khởi động FastAPI cho quá trình vận hành thực tế.
+
+Mặc định, **auto-reload** bị tắt. Nó cũng lắng nghe địa chỉ IP `0.0.0.0`, đó là tất cả các địa chỉ IP có sẵn, như vậy nó sẽ được truy cập công khai bởi bất kỳ ai có thể giao tiếp với máy tính. Đây là cách bạn thường chạy nó trong sản phẩm hoàn thiện, ví dụ trong một container.
+
+Trong hầu hết các trường hợp, bạn sẽ (và nên) có một "proxy điểm cuối (termination proxy)" xử lý HTTPS cho bạn, điều này sẽ phụ thuộc vào cách bạn triển khai ứng dụng của bạn, nhà cung cấp có thể làm điều này cho bạn, hoặc bạn có thể cần thiết lập nó.
+
+/// tip
+
+Bạn có thể tìm hiểu thêm về FastAPI CLI trong [tài liệu triển khai](deployment/index.md){.internal-link target=_blank}.
+
+///
diff --git a/docs/vi/docs/features.md b/docs/vi/docs/features.md
new file mode 100644
index 000000000..2220d9fa5
--- /dev/null
+++ b/docs/vi/docs/features.md
@@ -0,0 +1,200 @@
+# Tính năng
+
+## Tính năng của FastAPI
+
+**FastAPI** cho bạn những tính năng sau:
+
+### Dựa trên những tiêu chuẩn mở
+
+*
OpenAPI cho việc tạo API, bao gồm những khai báo về
đường dẫn các toán tử, tham số, body requests, cơ chế bảo mật, etc.
+* Tự động tài liệu hóa data model theo
JSON Schema (OpenAPI bản thân nó được dựa trên JSON Schema).
+* Được thiết kế xung quanh các tiêu chuẩn này sau khi nghiên cứu tỉ mỉ thay vì chỉ suy nghĩ đơn giản và sơ xài.
+* Điều này cho phép tự động hóa **trình sinh code client** cho nhiều ngôn ngữ lập trình khác nhau.
+
+### Tự động hóa tài liệu
+
+
+Tài liệu tương tác API và web giao diện người dùng. Là một framework được dựa trên OpenAPI do đó có nhiều tùy chọn giao diện cho tài liệu API, 2 giao diện bên dưới là mặc định.
+
+*
Swagger UI, với giao diện khám phá, gọi và kiểm thử API trực tiếp từ trình duyệt.
+
+
+
+* Thay thế với tài liệu API với
ReDoc.
+
+
+
+### Chỉ cần phiên bản Python hiện đại
+
+Tất cả được dựa trên khai báo kiểu dữ liệu chuẩn của **Python 3.8** (cảm ơn Pydantic). Bạn không cần học cú pháp mới, chỉ cần biết chuẩn Python hiện đại.
+
+Nếu bạn cần 2 phút để làm mới lại cách sử dụng các kiểu dữ liệu mới của Python (thậm chí nếu bạn không sử dụng FastAPI), xem hướng dẫn ngắn: [Kiểu dữ liệu Python](python-types.md){.internal-link target=_blank}.
+
+Bạn viết chuẩn Python với kiểu dữ liệu như sau:
+
+```Python
+from datetime import date
+
+from pydantic import BaseModel
+
+# Declare a variable as a str
+# and get editor support inside the function
+def main(user_id: str):
+ return user_id
+
+
+# A Pydantic model
+class User(BaseModel):
+ id: int
+ name: str
+ joined: date
+```
+
+Sau đó có thể được sử dụng:
+
+```Python
+my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
+
+second_user_data = {
+ "id": 4,
+ "name": "Mary",
+ "joined": "2018-11-30",
+}
+
+my_second_user: User = User(**second_user_data)
+```
+
+/// info
+
+`**second_user_data` nghĩa là:
+
+Truyền các khóa và giá trị của dict `second_user_data` trực tiếp như các tham số kiểu key-value, tương đương với: `User(id=4, name="Mary", joined="2018-11-30")`
+
+///
+
+### Được hỗ trợ từ các trình soạn thảo
+
+
+Toàn bộ framework được thiết kế để sử dụng dễ dàng và trực quan, toàn bộ quyết định đã được kiểm thử trên nhiều trình soạn thảo thậm chí trước khi bắt đầu quá trình phát triển, để chắc chắn trải nghiệm phát triển là tốt nhất.
+
+Trong lần khảo sát cuối cùng dành cho các lập trình viên Python, đã rõ ràng
rằng đa số các lập trình viên sử dụng tính năng "autocompletion".
+
+Toàn bộ framework "FastAPI" phải đảm bảo rằng: autocompletion hoạt động ở mọi nơi. Bạn sẽ hiếm khi cần quay lại để đọc tài liệu.
+
+Đây là các trình soạn thảo có thể giúp bạn:
+
+* trong
Visual Studio Code:
+
+
+
+* trong
PyCharm:
+
+
+
+Bạn sẽ có được auto-completion trong code, thậm chí trước đó là không thể. Như trong ví dụ, khóa `price` bên trong một JSON (đó có thể được lồng nhau) đến từ một request.
+
+Không còn nhập sai tên khóa, quay đi quay lại giữa các tài liệu hoặc cuộn lên cuộn xuống để tìm xem cuối cùng bạn đã sử dụng `username` hay `user_name`.
+
+### Ngắn gọn
+
+FastAPI có các giá trị mặc định hợp lý cho mọi thứ, với các cấu hình tùy chọn ở mọi nơi. Tất cả các tham số có thể được tinh chỉnh để thực hiện những gì bạn cần và để định nghĩa API bạn cần.
+
+Nhưng mặc định, tất cả **đều hoạt động**.
+
+### Validation
+
+* Validation cho đa số (hoặc tất cả?) **các kiểu dữ liệu** Python, bao gồm:
+ * JSON objects (`dict`).
+ * Mảng JSON (`list`) định nghĩa kiểu dữ liệu từng phần tử.
+ * Xâu (`str`), định nghĩa độ dài lớn nhất, nhỏ nhất.
+ * Số (`int`, `float`) với các giá trị lớn nhất, nhỏ nhất, etc.
+
+* Validation cho nhiều kiểu dữ liệu bên ngoài như:
+ * URL.
+ * Email.
+ * UUID.
+ * ...và nhiều cái khác.
+
+Tất cả validation được xử lí bằng những thiết lập tốt và mạnh mẽ của **Pydantic**.
+
+### Bảo mật và xác thực
+
+Bảo mật và xác thực đã tích hợp mà không làm tổn hại tới cơ sở dữ liệu hoặc data models.
+
+Tất cả cơ chế bảo mật định nghĩa trong OpenAPI, bao gồm:
+
+* HTTP Basic.
+* **OAuth2** (với **JWT tokens**). Xem hướng dẫn [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
+* API keys in:
+ * Headers.
+ * Các tham số trong query string.
+ * Cookies, etc.
+
+Cộng với tất cả các tính năng bảo mật từ Starlette (bao gồm **session cookies**).
+
+Tất cả được xây dựng dưới dạng các công cụ và thành phần có thể tái sử dụng, dễ dàng tích hợp với hệ thống, kho lưu trữ dữ liệu, cơ sở dữ liệu quan hệ và NoSQL của bạn,...
+
+### Dependency Injection
+
+FastAPI bao gồm một hệ thống
Dependency Injection vô cùng dễ sử dụng nhưng vô cùng mạnh mẽ.
+
+* Thậm chí, các dependency có thể có các dependency khác, tạo thành một phân cấp hoặc **"một đồ thị" của các dependency**.
+* Tất cả **được xử lí tự động** bởi framework.
+* Tất cả các dependency có thể yêu cầu dữ liệu từ request và **tăng cường các ràng buộc từ đường dẫn** và tự động tài liệu hóa.
+* **Tự động hóa validation**, thậm chí với các tham số *đường dẫn* định nghĩa trong các dependency.
+* Hỗ trợ hệ thống xác thực người dùng phức tạp, **các kết nối cơ sở dữ liệu**,...
+* **Không làm tổn hại** cơ sở dữ liệu, frontends,... Nhưng dễ dàng tích hợp với tất cả chúng.
+
+### Không giới hạn "plug-ins"
+
+Hoặc theo một cách nào khác, không cần chúng, import và sử dụng code bạn cần.
+
+Bất kì tích hợp nào được thiết kế để sử dụng đơn giản (với các dependency), đến nỗi bạn có thể tạo một "plug-in" cho ứng dụng của mình trong 2 dòng code bằng cách sử dụng cùng một cấu trúc và cú pháp được sử dụng cho *path operations* của bạn.
+
+### Đã được kiểm thử
+
+* 100%
test coverage.
+* 100%
type annotated code base.
+* Được sử dụng cho các ứng dụng sản phẩm.
+
+## Tính năng của Starlette
+
+`FastAPI` is thực sự là một sub-class của `Starlette`. Do đó, nếu bạn đã biết hoặc đã sử dụng Starlette, đa số các chức năng sẽ làm việc giống như vậy.
+
+Với **FastAPI**, bạn có được tất cả những tính năng của **Starlette**:
+
+* Hiệu năng thực sự ấn tượng. Nó là
một trong nhưng framework Python nhanh nhất, khi so sánh với **NodeJS** và **Go**.
+* Hỗ trợ **WebSocket**.
+* In-process background tasks.
+* Startup and shutdown events.
+* Client cho kiểm thử xây dựng trên HTTPX.
+* **CORS**, GZip, Static Files, Streaming responses.
+* Hỗ trợ **Session and Cookie**.
+* 100% test coverage.
+* 100% type annotated codebase.
+
+## Tính năng của Pydantic
+
+**FastAPI** tương thích đầy đủ với (và dựa trên)
Pydantic. Do đó, bất kì code Pydantic nào bạn thêm vào cũng sẽ hoạt động.
+
+Bao gồm các thư viện bên ngoài cũng dựa trên Pydantic, như
ORMs,
ODMs cho cơ sở dữ liệu.
+
+Nó cũng có nghĩa là trong nhiều trường hợp, bạn có thể truyền cùng object bạn có từ một request **trực tiếp cho cơ sở dữ liệu**, vì mọi thứ được validate tự động.
+
+Điều tương tự áp dụng cho các cách khác nhau, trong nhiều trường hợp, bạn có thể chỉ truyền object từ cơ sở dữ liêu **trực tiếp tới client**.
+
+Với **FastAPI**, bạn có tất cả những tính năng của **Pydantic** (FastAPI dựa trên Pydantic cho tất cả những xử lí về dữ liệu):
+
+* **Không gây rối não**:
+ * Không cần học ngôn ngữ mô tả cấu trúc mới.
+ * Nếu bạn biết kiểu dữ liệu Python, bạn biết cách sử dụng Pydantic.
+* Sử dụng tốt với **
IDE/
linter/não của bạn**:
+
+ * Bởi vì các cấu trúc dữ liệu của Pydantic chỉ là các instances của class bạn định nghĩa; auto-completion, linting, mypy và trực giác của bạn nên làm việc riêng biệt với những dữ liệu mà bạn đã validate.
+* Validate **các cấu trúc phức tạp**:
+ * Sử dụng các models Pydantic phân tầng, `List` và `Dict` của Python `typing`,...
+ * Và các validators cho phép các cấu trúc dữ liệu phức tạp trở nên rõ ràng và dễ dàng để định nghĩa, kiểm tra và tài liệu hóa thành JSON Schema.
+ * Bạn có thể có các object **JSON lồng nhau** và tất cả chúng đã validate và annotated.
+* **Có khả năng mở rộng**:
+ * Pydantic cho phép bạn tùy chỉnh kiểu dữ liệu bằng việc định nghĩa hoặc bạn có thể mở rộng validation với các decorator trong model.
+* 100% test coverage.
diff --git a/docs/vi/docs/index.md b/docs/vi/docs/index.md
new file mode 100644
index 000000000..5c6b7e8a4
--- /dev/null
+++ b/docs/vi/docs/index.md
@@ -0,0 +1,475 @@
+# FastAPI
+
+
+
+
+
+
+
+ FastAPI framework, hiệu năng cao, dễ học, dễ code, sẵn sàng để tạo ra sản phẩm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+**Tài liệu**:
https://fastapi.tiangolo.com
+
+**Mã nguồn**:
https://github.com/fastapi/fastapi
+
+---
+
+FastAPI là một web framework hiện đại, hiệu năng cao để xây dựng web APIs với Python dựa trên tiêu chuẩn Python type hints.
+
+Những tính năng như:
+
+* **Nhanh**: Hiệu năng rất cao khi so sánh với **NodeJS** và **Go** (cảm ơn Starlette và Pydantic). [Một trong những Python framework nhanh nhất](#hieu-nang).
+* **Code nhanh**: Tăng tốc độ phát triển tính năng từ 200% tới 300%. *
+* **Ít lỗi hơn**: Giảm khoảng 40% những lỗi phát sinh bởi con người (nhà phát triển). *
+* **Trực giác tốt hơn**: Được các trình soạn thảo hỗ tuyệt vời.
Completion mọi nơi. Ít thời gian gỡ lỗi.
+* **Dễ dàng**: Được thiết kế để dễ dàng học và sử dụng. Ít thời gian đọc tài liệu.
+* **Ngắn**: Tối thiểu code bị trùng lặp. Nhiều tính năng được tích hợp khi định nghĩa tham số. Ít lỗi hơn.
+* **Tăng tốc**: Có được sản phẩm cùng với tài liệu (được tự động tạo) có thể tương tác.
+* **Được dựa trên các tiêu chuẩn**: Dựa trên (và hoàn toàn tương thích với) các tiêu chuẩn mở cho APIs :
OpenAPI (trước đó được biết đến là Swagger) và
JSON Schema.
+
+
* ước tính được dựa trên những kiểm chứng trong nhóm phát triển nội bộ, xây dựng các ứng dụng sản phẩm.
+
+## Nhà tài trợ
+
+
+
+{% if sponsors %}
+{% for sponsor in sponsors.gold -%}
+

+{% endfor -%}
+{%- for sponsor in sponsors.silver -%}
+

+{% endfor %}
+{% endif %}
+
+
+
+
Những nhà tài trợ khác
+
+## Ý kiến đánh giá
+
+"_[...] Tôi đang sử dụng **FastAPI** vô cùng nhiều vào những ngày này. [...] Tôi thực sự đang lên kế hoạch sử dụng nó cho tất cả các nhóm **dịch vụ ML tại Microsoft**. Một vài trong số đó đang tích hợp vào sản phẩm lõi của **Window** và một vài sản phẩm cho **Office**._"
+
+
Kabir Khan -
Microsoft (ref)
+
+---
+
+"_Chúng tôi tích hợp thư viện **FastAPI** để sinh ra một **REST** server, nó có thể được truy vấn để thu được những **dự đoán**._ [bởi Ludwid] "
+
+
Piero Molino, Yaroslav Dudin, và Sai Sumanth Miryala -
Uber (ref)
+
+---
+
+"_**Netflix** vui mừng thông báo việc phát hành framework mã nguồn mở của chúng tôi cho *quản lí khủng hoảng* tập trung: **Dispatch**! [xây dựng với **FastAPI**]_"
+
+
Kevin Glisson, Marc Vilanova, Forest Monsen -
Netflix (ref)
+
+---
+
+"_Tôi vô cùng hào hứng về **FastAPI**. Nó rất thú vị_"
+
+
+
+---
+
+"_Thành thật, những gì bạn đã xây dựng nhìn siêu chắc chắn và bóng bẩy. Theo nhiều cách, nó là những gì tôi đã muốn Hug trở thành - thật sự truyền cảm hứng để thấy ai đó xây dựng nó._"
+
+
Timothy Crosley - người tạo ra
Hug (ref)
+
+---
+
+"_Nếu bạn đang tìm kiếm một **framework hiện đại** để xây dựng một REST APIs, thử xem xét **FastAPI** [...] Nó nhanh, dễ dùng và dễ học [...]_"
+
+"_Chúng tôi đã chuyển qua **FastAPI cho **APIs** của chúng tôi [...] Tôi nghĩ bạn sẽ thích nó [...]_"
+
+
+
+
+---
+
+"_Nếu ai đó đang tìm cách xây dựng sản phẩm API bằng Python, tôi sẽ đề xuất **FastAPI**. Nó **được thiết kế đẹp đẽ**, **sử dụng đơn giản** và **có khả năng mở rộng cao**, nó đã trở thành một **thành phần quan trọng** trong chiến lược phát triển API của chúng tôi và đang thúc đẩy nhiều dịch vụ và mảng tự động hóa như Kỹ sư TAC ảo của chúng tôi._"
+
+
Deon Pillsbury -
Cisco (ref)
+
+---
+
+## **Typer**, giao diện dòng lệnh của FastAPI
+
+

+
+Nếu bạn đang xây dựng một
CLI - ứng dụng được sử dụng trong giao diện dòng lệnh, xem về
**Typer**.
+
+**Typer** là một người anh em của FastAPI. Và nó được dự định trở thành **giao diện dòng lệnh cho FastAPI**. ⌨️ 🚀
+
+## Yêu cầu
+
+FastAPI đứng trên vai những người khổng lồ:
+
+*
Starlette cho phần web.
+*
Pydantic cho phần data.
+
+## Cài đặt
+
+
+
+```console
+$ pip install fastapi
+
+---> 100%
+```
+
+
+
+Bạn cũng sẽ cần một ASGI server cho production như
Uvicorn hoặc
Hypercorn.
+
+
+
+```console
+$ pip install "uvicorn[standard]"
+
+---> 100%
+```
+
+
+
+## Ví dụ
+
+### Khởi tạo
+
+* Tạo một tệp tin `main.py` như sau:
+
+```Python
+from typing import Union
+
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+def read_root():
+ return {"Hello": "World"}
+
+
+@app.get("/items/{item_id}")
+def read_item(item_id: int, q: Union[str, None] = None):
+ return {"item_id": item_id, "q": q}
+```
+
+
+Hoặc sử dụng async def
...
+
+Nếu code của bạn sử dụng `async` / `await`, hãy sử dụng `async def`:
+
+```Python hl_lines="9 14"
+from typing import Union
+
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+async def read_root():
+ return {"Hello": "World"}
+
+
+@app.get("/items/{item_id}")
+async def read_item(item_id: int, q: Union[str, None] = None):
+ return {"item_id": item_id, "q": q}
+```
+
+**Lưu ý**:
+
+Nếu bạn không biết, xem phần _"In a hurry?"_ về `async` và `await` trong tài liệu này.
+
+
+
+### Chạy ứng dụng
+
+Chạy server như sau:
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [28720]
+INFO: Started server process [28722]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+
+Về lệnh uvicorn main:app --reload
...
+
+Lệnh `uvicorn main:app` tham chiếu tới những thành phần sau:
+
+* `main`: tệp tin `main.py` (một Python "module").
+* `app`: object được tạo trong tệp tin `main.py` tại dòng `app = FastAPI()`.
+* `--reload`: chạy lại server sau khi code thay đổi. Chỉ sử dụng trong quá trình phát triển.
+
+
+
+### Kiểm tra
+
+Mở trình duyệt của bạn tại
http://127.0.0.1:8000/items/5?q=somequery.
+
+Bạn sẽ thấy một JSON response:
+
+```JSON
+{"item_id": 5, "q": "somequery"}
+```
+
+Bạn đã sẵn sàng để tạo một API như sau:
+
+* Nhận HTTP request với _đường dẫn_ `/` và `/items/{item_id}`.
+* Cả hai _đường dẫn_ sử dụng
toán tử `GET` (cũng đươc biết đến là _phương thức_ HTTP).
+* _Đường dẫn_ `/items/{item_id}` có một _tham số đường dẫn_ `item_id`, nó là một tham số kiểu `int`.
+* _Đường dẫn_ `/items/{item_id}` có một _tham số query string_ `q`, nó là một tham số tùy chọn kiểu `str`.
+
+### Tài liệu tương tác API
+
+Truy cập
http://127.0.0.1:8000/docs.
+
+Bạn sẽ thấy tài liệu tương tác API được tạo tự động (cung cấp bởi
Swagger UI):
+
+
+
+### Tài liệu API thay thế
+
+Và bây giờ, hãy truy cập tới
http://127.0.0.1:8000/redoc.
+
+Bạn sẽ thấy tài liệu được thay thế (cung cấp bởi
ReDoc):
+
+
+
+## Nâng cấp ví dụ
+
+Bây giờ sửa tệp tin `main.py` để nhận body từ một request `PUT`.
+
+Định nghĩa của body sử dụng kiểu dữ liệu chuẩn của Python, cảm ơn Pydantic.
+
+```Python hl_lines="4 9-12 25-27"
+from typing import Union
+
+from fastapi import FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ price: float
+ is_offer: Union[bool, None] = None
+
+
+@app.get("/")
+def read_root():
+ return {"Hello": "World"}
+
+
+@app.get("/items/{item_id}")
+def read_item(item_id: int, q: Union[str, None] = None):
+ return {"item_id": item_id, "q": q}
+
+
+@app.put("/items/{item_id}")
+def update_item(item_id: int, item: Item):
+ return {"item_name": item.name, "item_id": item_id}
+```
+
+Server nên tự động chạy lại (bởi vì bạn đã thêm `--reload` trong lệnh `uvicorn` ở trên).
+
+### Nâng cấp tài liệu API
+
+Bây giờ truy cập tới
http://127.0.0.1:8000/docs.
+
+* Tài liệu API sẽ được tự động cập nhật, bao gồm body mới:
+
+
+
+* Click vào nút "Try it out", nó cho phép bạn điền những tham số và tương tác trực tiếp với API:
+
+
+
+* Sau khi click vào nút "Execute", giao diện người dùng sẽ giao tiếp với API của bạn bao gồm: gửi các tham số, lấy kết quả và hiển thị chúng trên màn hình:
+
+
+
+### Nâng cấp tài liệu API thay thế
+
+Và bây giờ truy cập tới
http://127.0.0.1:8000/redoc.
+
+* Tài liệu thay thế cũng sẽ phản ánh tham số và body mới:
+
+
+
+### Tóm lại
+
+Bạn khai báo **một lần** kiểu dữ liệu của các tham số, body, etc là các tham số của hàm số.
+
+Bạn định nghĩa bằng cách sử dụng các kiểu dữ liệu chuẩn của Python.
+
+Bạn không phải học một cú pháp mới, các phương thức và class của một thư viện cụ thể nào.
+
+Chỉ cần sử dụng các chuẩn của **Python**.
+
+Ví dụ, với một tham số kiểu `int`:
+
+```Python
+item_id: int
+```
+
+hoặc với một model `Item` phức tạp hơn:
+
+```Python
+item: Item
+```
+
+...và với định nghĩa đơn giản đó, bạn có được:
+
+* Sự hỗ trợ từ các trình soạn thảo, bao gồm:
+ * Completion.
+ * Kiểm tra kiểu dữ liệu.
+* Kiểm tra kiểu dữ liệu:
+ * Tự động sinh lỗi rõ ràng khi dữ liệu không hợp lệ .
+ * Kiểm tra JSON lồng nhau .
+*
Chuyển đổi dữ liệu đầu vào: tới từ network sang dữ liệu kiểu Python. Đọc từ:
+ * JSON.
+ * Các tham số trong đường dẫn.
+ * Các tham số trong query string.
+ * Cookies.
+ * Headers.
+ * Forms.
+ * Files.
+*
Chuyển đổi dữ liệu đầu ra: chuyển đổi từ kiểu dữ liệu Python sang dữ liệu network (như JSON):
+ * Chuyển đổi kiểu dữ liệu Python (`str`, `int`, `float`, `bool`, `list`,...).
+ * `datetime` objects.
+ * `UUID` objects.
+ * Database models.
+ * ...và nhiều hơn thế.
+* Tự động tạo tài liệu tương tác API, bao gồm 2 giao diện người dùng:
+ * Swagger UI.
+ * ReDoc.
+
+---
+
+Quay trở lại ví dụ trước, **FastAPI** sẽ thực hiện:
+
+* Kiểm tra xem có một `item_id` trong đường dẫn với các request `GET` và `PUT` không?
+* Kiểm tra xem `item_id` có phải là kiểu `int` trong các request `GET` và `PUT` không?
+ * Nếu không, client sẽ thấy một lỗi rõ ràng và hữu ích.
+* Kiểm tra xem nếu có một tham số `q` trong query string (ví dụ như `http://127.0.0.1:8000/items/foo?q=somequery`) cho request `GET`.
+ * Tham số `q` được định nghĩa `= None`, nó là tùy chọn.
+ * Nếu không phải `None`, nó là bắt buộc (như body trong trường hợp của `PUT`).
+* Với request `PUT` tới `/items/{item_id}`, đọc body như JSON:
+ * Kiểm tra xem nó có một thuộc tính bắt buộc kiểu `str` là `name` không?
+ * Kiểm tra xem nó có một thuộc tính bắt buộc kiểu `float` là `price` không?
+ * Kiểm tra xem nó có một thuộc tính tùy chọn là `is_offer` không? Nếu có, nó phải có kiểu `bool`.
+ * Tất cả những kiểm tra này cũng được áp dụng với các JSON lồng nhau.
+* Chuyển đổi tự động các JSON object đến và JSON object đi.
+* Tài liệu hóa mọi thứ với OpenAPI, tài liệu đó có thể được sử dụng bởi:
+
+ * Các hệ thống tài liệu có thể tương tác.
+ * Hệ thống sinh code tự động, cho nhiều ngôn ngữ lập trình.
+* Cung cấp trực tiếp 2 giao diện web cho tài liệu tương tác
+
+---
+
+Chúng tôi chỉ trình bày những thứ cơ bản bên ngoài, nhưng bạn đã hiểu cách thức hoạt động của nó.
+
+Thử thay đổi dòng này:
+
+```Python
+ return {"item_name": item.name, "item_id": item_id}
+```
+
+...từ:
+
+```Python
+ ... "item_name": item.name ...
+```
+
+...sang:
+
+```Python
+ ... "item_price": item.price ...
+```
+
+...và thấy trình soạn thảo của bạn nhận biết kiểu dữ liệu và gợi ý hoàn thiện các thuộc tính.
+
+
+
+Ví dụ hoàn chỉnh bao gồm nhiều tính năng hơn, xem
Tutorial - User Guide.
+
+
+**Cảnh báo tiết lỗ**: Tutorial - User Guide:
+
+* Định nghĩa **tham số** từ các nguồn khác nhau như: **headers**, **cookies**, **form fields** và **files**.
+* Cách thiết lập **các ràng buộc cho validation** như `maximum_length` hoặc `regex`.
+* Một hệ thống **
Dependency Injection vô cùng mạnh mẽ và dễ dàng sử dụng.
+* Bảo mật và xác thực, hỗ trợ **OAuth2**(với **JWT tokens**) và **HTTP Basic**.
+* Những kĩ thuật nâng cao hơn (nhưng tương đối dễ) để định nghĩa **JSON models lồng nhau** (cảm ơn Pydantic).
+* Tích hợp **GraphQL** với
Strawberry và các thư viện khác.
+* Nhiều tính năng mở rộng (cảm ơn Starlette) như:
+ * **WebSockets**
+ * kiểm thử vô cùng dễ dàng dựa trên HTTPX và `pytest`
+ * **CORS**
+ * **Cookie Sessions**
+ * ...và nhiều hơn thế.
+
+## Hiệu năng
+
+Independent TechEmpower benchmarks cho thấy các ứng dụng **FastAPI** chạy dưới Uvicorn là
một trong những Python framework nhanh nhất, chỉ đứng sau Starlette và Uvicorn (được sử dụng bên trong FastAPI). (*)
+
+Để hiểu rõ hơn, xem phần
Benchmarks.
+
+## Các dependency tùy chọn
+
+Sử dụng bởi Pydantic:
+
+*
email-validator
- cho email validation.
+
+Sử dụng Starlette:
+
+*
httpx
- Bắt buộc nếu bạn muốn sử dụng `TestClient`.
+*
jinja2
- Bắt buộc nếu bạn muốn sử dụng cấu hình template engine mặc định.
+*
python-multipart
- Bắt buộc nếu bạn muốn hỗ trợ
"parsing", form với `request.form()`.
+*
itsdangerous
- Bắt buộc để hỗ trợ `SessionMiddleware`.
+*
pyyaml
- Bắt buộc để hỗ trợ `SchemaGenerator` cho Starlette (bạn có thể không cần nó trong FastAPI).
+
+Sử dụng bởi FastAPI / Starlette:
+
+*
uvicorn
- Server để chạy ứng dụng của bạn.
+*
orjson
- Bắt buộc nếu bạn muốn sử dụng `ORJSONResponse`.
+*
ujson
- Bắt buộc nếu bạn muốn sử dụng `UJSONResponse`.
+
+Bạn có thể cài đặt tất cả những dependency trên với `pip install "fastapi[all]"`.
+
+## Giấy phép
+
+Dự án này được cấp phép dưới những điều lệ của giấy phép MIT.
diff --git a/docs/vi/docs/python-types.md b/docs/vi/docs/python-types.md
new file mode 100644
index 000000000..403e89930
--- /dev/null
+++ b/docs/vi/docs/python-types.md
@@ -0,0 +1,593 @@
+# Giới thiệu kiểu dữ liệu Python
+
+Python hỗ trợ tùy chọn "type hints" (còn được gọi là "type annotations").
+
+Những **"type hints"** hay chú thích là một cú pháp đặc biệt cho phép khai báo
kiểu dữ liệu của một biến.
+
+Bằng việc khai báo kiểu dữ liệu cho các biến của bạn, các trình soạn thảo và các công cụ có thể hỗ trợ bạn tốt hơn.
+
+Đây chỉ là một **hướng dẫn nhanh** về gợi ý kiểu dữ liệu trong Python. Nó chỉ bao gồm những điều cần thiết tối thiểu để sử dụng chúng với **FastAPI**... đó thực sự là rất ít.
+
+**FastAPI** hoàn toàn được dựa trên những gợi ý kiểu dữ liệu, chúng mang đến nhiều ưu điểm và lợi ích.
+
+Nhưng thậm chí nếu bạn không bao giờ sử dụng **FastAPI**, bạn sẽ được lợi từ việc học một ít về chúng.
+
+/// note
+
+Nếu bạn là một chuyên gia về Python, và bạn đã biết mọi thứ về gợi ý kiểu dữ liệu, bỏ qua và đi tới chương tiếp theo.
+
+///
+
+## Động lực
+
+Hãy bắt đầu với một ví dụ đơn giản:
+
+{* ../../docs_src/python_types/tutorial001.py *}
+
+
+Kết quả khi gọi chương trình này:
+
+```
+John Doe
+```
+
+Hàm thực hiện như sau:
+
+* Lấy một `first_name` và `last_name`.
+* Chuyển đổi kí tự đầu tiên của mỗi biến sang kiểu chữ hoa với `title()`.
+*
Nối chúng lại với nhau bằng một kí tự trắng ở giữa.
+
+{* ../../docs_src/python_types/tutorial001.py hl[2] *}
+
+
+### Sửa đổi
+
+Nó là một chương trình rất đơn giản.
+
+Nhưng bây giờ hình dung rằng bạn đang viết nó từ đầu.
+
+Tại một vài thời điểm, bạn sẽ bắt đầu định nghĩa hàm, bạn có các tham số...
+
+Nhưng sau đó bạn phải gọi "phương thức chuyển đổi kí tự đầu tiên sang kiểu chữ hoa".
+
+Có phải là `upper`? Có phải là `uppercase`? `first_uppercase`? `capitalize`?
+
+Sau đó, bạn thử hỏi người bạn cũ của mình, autocompletion của trình soạn thảo.
+
+Bạn gõ tham số đầu tiên của hàm, `first_name`, sau đó một dấu chấm (`.`) và sau đó ấn `Ctrl+Space` để kích hoạt bộ hoàn thành.
+
+Nhưng đáng buồn, bạn không nhận được điều gì hữu ích cả:
+
+

+
+### Thêm kiểu dữ liệu
+
+Hãy sửa một dòng từ phiên bản trước.
+
+Chúng ta sẽ thay đổi chính xác đoạn này, tham số của hàm, từ:
+
+```Python
+ first_name, last_name
+```
+
+sang:
+
+```Python
+ first_name: str, last_name: str
+```
+
+Chính là nó.
+
+Những thứ đó là "type hints":
+
+{* ../../docs_src/python_types/tutorial002.py hl[1] *}
+
+
+Đó không giống như khai báo những giá trị mặc định giống như:
+
+```Python
+ first_name="john", last_name="doe"
+```
+
+Nó là một thứ khác.
+
+Chúng ta sử dụng dấu hai chấm (`:`), không phải dấu bằng (`=`).
+
+Và việc thêm gợi ý kiểu dữ liệu không làm thay đổi những gì xảy ra so với khi chưa thêm chúng.
+
+But now, imagine you are again in the middle of creating that function, but with type hints.
+
+Tại cùng một điểm, bạn thử kích hoạt autocomplete với `Ctrl+Space` và bạn thấy:
+
+

+
+Với cái đó, bạn có thể cuộn, nhìn thấy các lựa chọn, cho đến khi bạn tìm thấy một "tiếng chuông":
+
+

+
+## Động lực nhiều hơn
+
+Kiểm tra hàm này, nó đã có gợi ý kiểu dữ liệu:
+
+{* ../../docs_src/python_types/tutorial003.py hl[1] *}
+
+
+Bởi vì trình soạn thảo biết kiểu dữ liệu của các biến, bạn không chỉ có được completion, bạn cũng được kiểm tra lỗi:
+
+

+
+Bây giờ bạn biết rằng bạn phải sửa nó, chuyển `age` sang một xâu với `str(age)`:
+
+{* ../../docs_src/python_types/tutorial004.py hl[2] *}
+
+
+## Khai báo các kiểu dữ liệu
+
+Bạn mới chỉ nhìn thấy những nơi chủ yếu để đặt khai báo kiểu dữ liệu. Như là các tham số của hàm.
+
+Đây cũng là nơi chủ yếu để bạn sử dụng chúng với **FastAPI**.
+
+### Kiểu dữ liệu đơn giản
+
+Bạn có thể khai báo tất cả các kiểu dữ liệu chuẩn của Python, không chỉ là `str`.
+
+Bạn có thể sử dụng, ví dụ:
+
+* `int`
+* `float`
+* `bool`
+* `bytes`
+
+{* ../../docs_src/python_types/tutorial005.py hl[1] *}
+
+
+### Các kiểu dữ liệu tổng quát với tham số kiểu dữ liệu
+
+Có một vài cấu trúc dữ liệu có thể chứa các giá trị khác nhau như `dict`, `list`, `set` và `tuple`. Và những giá trị nội tại cũng có thể có kiểu dữ liệu của chúng.
+
+Những kiểu dữ liệu nội bộ này được gọi là những kiểu dữ liệu "**tổng quát**". Và có khả năng khai báo chúng, thậm chí với các kiểu dữ liệu nội bộ của chúng.
+
+Để khai báo những kiểu dữ liệu và những kiểu dữ liệu nội bộ đó, bạn có thể sử dụng mô đun chuẩn của Python là `typing`. Nó có hỗ trợ những gợi ý kiểu dữ liệu này.
+
+#### Những phiên bản mới hơn của Python
+
+Cú pháp sử dụng `typing` **tương thích** với tất cả các phiên bản, từ Python 3.6 tới những phiên bản cuối cùng, bao gồm Python 3.9, Python 3.10,...
+
+As Python advances, **những phiên bản mới** mang tới sự hỗ trợ được cải tiến cho những chú thích kiểu dữ liệu và trong nhiều trường hợp bạn thậm chí sẽ không cần import và sử dụng mô đun `typing` để khai báo chú thích kiểu dữ liệu.
+
+Nếu bạn có thể chọn một phiên bản Python gần đây hơn cho dự án của bạn, ban sẽ có được những ưu điểm của những cải tiến đơn giản đó.
+
+Trong tất cả các tài liệu tồn tại những ví dụ tương thích với mỗi phiên bản Python (khi có một sự khác nhau).
+
+Cho ví dụ "**Python 3.6+**" có nghĩa là nó tương thích với Python 3.7 hoặc lớn hơn (bao gồm 3.7, 3.8, 3.9, 3.10,...). và "**Python 3.9+**" nghĩa là nó tương thích với Python 3.9 trở lên (bao gồm 3.10,...).
+
+Nếu bạn có thể sử dụng **phiên bản cuối cùng của Python**, sử dụng những ví dụ cho phiên bản cuối, những cái đó sẽ có **cú pháp đơn giản và tốt nhât**, ví dụ, "**Python 3.10+**".
+
+#### List
+
+Ví dụ, hãy định nghĩa một biến là `list` các `str`.
+
+//// tab | Python 3.9+
+
+Khai báo biến với cùng dấu hai chấm (`:`).
+
+Tương tự kiểu dữ liệu `list`.
+
+Như danh sách là một kiểu dữ liệu chứa một vài kiểu dữ liệu có sẵn, bạn đặt chúng trong các dấu ngoặc vuông:
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial006_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+Từ `typing`, import `List` (với chữ cái `L` viết hoa):
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial006.py!}
+```
+
+Khai báo biến với cùng dấu hai chấm (`:`).
+
+Tương tự như kiểu dữ liệu, `List` bạn import từ `typing`.
+
+Như danh sách là một kiểu dữ liệu chứa các kiểu dữ liệu có sẵn, bạn đặt chúng bên trong dấu ngoặc vuông:
+
+```Python hl_lines="4"
+{!> ../../docs_src/python_types/tutorial006.py!}
+```
+
+////
+
+/// info
+
+Các kiểu dữ liệu có sẵn bên trong dấu ngoặc vuông được gọi là "tham số kiểu dữ liệu".
+
+Trong trường hợp này, `str` là tham số kiểu dữ liệu được truyền tới `List` (hoặc `list` trong Python 3.9 trở lên).
+
+///
+
+Có nghĩa là: "biến `items` là một `list`, và mỗi phần tử trong danh sách này là một `str`".
+
+/// tip
+
+Nếu bạn sử dụng Python 3.9 hoặc lớn hơn, bạn không phải import `List` từ `typing`, bạn có thể sử dụng `list` để thay thế.
+
+///
+
+Bằng cách này, trình soạn thảo của bạn có thể hỗ trợ trong khi xử lí các phần tử trong danh sách:
+
+

+
+Đa phần đều không thể đạt được nếu không có các kiểu dữ liệu.
+
+Chú ý rằng, biến `item` là một trong các phần tử trong danh sách `items`.
+
+Và do vậy, trình soạn thảo biết nó là một `str`, và cung cấp sự hỗ trợ cho nó.
+
+#### Tuple and Set
+
+Bạn sẽ làm điều tương tự để khai báo các `tuple` và các `set`:
+
+//// tab | Python 3.9+
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial007_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial007.py!}
+```
+
+////
+
+Điều này có nghĩa là:
+
+* Biến `items_t` là một `tuple` với 3 phần tử, một `int`, một `int` nữa, và một `str`.
+* Biến `items_s` là một `set`, và mỗi phần tử của nó có kiểu `bytes`.
+
+#### Dict
+
+Để định nghĩa một `dict`, bạn truyền 2 tham số kiểu dữ liệu, phân cách bởi dấu phẩy.
+
+Tham số kiểu dữ liệu đầu tiên dành cho khóa của `dict`.
+
+Tham số kiểu dữ liệu thứ hai dành cho giá trị của `dict`.
+
+//// tab | Python 3.9+
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial008_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial008.py!}
+```
+
+////
+
+Điều này có nghĩa là:
+
+* Biến `prices` là một `dict`:
+ * Khóa của `dict` này là kiểu `str` (đó là tên của mỗi vật phẩm).
+ * Giá trị của `dict` này là kiểu `float` (đó là giá của mỗi vật phẩm).
+
+#### Union
+
+Bạn có thể khai báo rằng một biến có thể là **một vài kiểu dữ liệu" bất kì, ví dụ, một `int` hoặc một `str`.
+
+Trong Python 3.6 hoặc lớn hơn (bao gồm Python 3.10) bạn có thể sử dụng kiểu `Union` từ `typing` và đặt trong dấu ngoặc vuông những giá trị được chấp nhận.
+
+In Python 3.10 there's also a **new syntax** where you can put the possible types separated by a
vertical bar (`|`).
+
+Trong Python 3.10 cũng có một **cú pháp mới** mà bạn có thể đặt những kiểu giá trị khả thi phân cách bởi một dấu
sổ dọc (`|`).
+
+
+//// tab | Python 3.10+
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial008b_py310.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial008b.py!}
+```
+
+////
+
+Trong cả hai trường hợp có nghĩa là `item` có thể là một `int` hoặc `str`.
+
+#### Khả năng `None`
+
+Bạn có thể khai báo một giá trị có thể có một kiểu dữ liệu, giống như `str`, nhưng nó cũng có thể là `None`.
+
+Trong Python 3.6 hoặc lớn hơn (bao gồm Python 3.10) bạn có thể khai báo nó bằng các import và sử dụng `Optional` từ mô đun `typing`.
+
+```Python hl_lines="1 4"
+{!../../docs_src/python_types/tutorial009.py!}
+```
+
+Sử dụng `Optional[str]` thay cho `str` sẽ cho phép trình soạn thảo giúp bạn phát hiện các lỗi mà bạn có thể gặp như một giá trị luôn là một `str`, trong khi thực tế nó rất có thể là `None`.
+
+`Optional[Something]` là một cách viết ngắn gọn của `Union[Something, None]`, chúng là tương đương nhau.
+
+Điều này cũng có nghĩa là trong Python 3.10, bạn có thể sử dụng `Something | None`:
+
+//// tab | Python 3.10+
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial009_py310.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial009.py!}
+```
+
+////
+
+//// tab | Python 3.8+ alternative
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial009b.py!}
+```
+
+////
+
+#### Sử dụng `Union` hay `Optional`
+
+If you are using a Python version below 3.10, here's a tip from my very **subjective** point of view:
+
+Nếu bạn đang sử dụng phiên bản Python dưới 3.10, đây là một mẹo từ ý kiến rất "chủ quan" của tôi:
+
+* 🚨 Tránh sử dụng `Optional[SomeType]`
+* Thay vào đó ✨ **sử dụng `Union[SomeType, None]`** ✨.
+
+Cả hai là tương đương và bên dưới chúng giống nhau, nhưng tôi sẽ đễ xuất `Union` thay cho `Optional` vì từ "**tùy chọn**" có vẻ ngầm định giá trị là tùy chọn, và nó thực sự có nghĩa rằng "nó có thể là `None`", do đó nó không phải là tùy chọn và nó vẫn được yêu cầu.
+
+Tôi nghĩ `Union[SomeType, None]` là rõ ràng hơn về ý nghĩa của nó.
+
+Nó chỉ là về các từ và tên. Nhưng những từ đó có thể ảnh hưởng cách bạn và những đồng đội của bạn suy nghĩ về code.
+
+Cho một ví dụ, hãy để ý hàm này:
+
+{* ../../docs_src/python_types/tutorial009c.py hl[1,4] *}
+
+
+Tham số `name` được định nghĩa là `Optional[str]`, nhưng nó **không phải là tùy chọn**, bạn không thể gọi hàm mà không có tham số:
+
+```Python
+say_hi() # Oh, no, this throws an error! 😱
+```
+
+Tham số `name` **vẫn được yêu cầu** (không phải là *tùy chọn*) vì nó không có giá trị mặc định. Trong khi đó, `name` chấp nhận `None` như là giá trị:
+
+```Python
+say_hi(name=None) # This works, None is valid 🎉
+```
+
+Tin tốt là, khi bạn sử dụng Python 3.10, bạn sẽ không phải lo lắng về điều đó, bạn sẽ có thể sử dụng `|` để định nghĩa hợp của các kiểu dữ liệu một cách đơn giản:
+
+{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *}
+
+
+Và sau đó, bạn sẽ không phải lo rằng những cái tên như `Optional` và `Union`. 😎
+
+
+#### Những kiểu dữ liệu tổng quát
+
+Những kiểu dữ liệu này lấy tham số kiểu dữ liệu trong dấu ngoặc vuông được gọi là **Kiểu dữ liệu tổng quát**, cho ví dụ:
+
+//// tab | Python 3.10+
+
+Bạn có thể sử dụng các kiểu dữ liệu có sẵn như là kiểu dữ liệu tổng quát (với ngoặc vuông và kiểu dữ liệu bên trong):
+
+* `list`
+* `tuple`
+* `set`
+* `dict`
+
+Và tương tự với Python 3.6, từ mô đun `typing`:
+
+* `Union`
+* `Optional` (tương tự như Python 3.6)
+* ...và các kiểu dữ liệu khác.
+
+Trong Python 3.10, thay vì sử dụng `Union` và `Optional`, bạn có thể sử dụng
sổ dọc ('|') để khai báo hợp của các kiểu dữ liệu, điều đó tốt hơn và đơn giản hơn nhiều.
+
+////
+
+//// tab | Python 3.9+
+
+Bạn có thể sử dụng các kiểu dữ liệu có sẵn tương tự như (với ngoặc vuông và kiểu dữ liệu bên trong):
+
+* `list`
+* `tuple`
+* `set`
+* `dict`
+
+Và tương tự với Python 3.6, từ mô đun `typing`:
+
+* `Union`
+* `Optional`
+* ...and others.
+
+////
+
+//// tab | Python 3.8+
+
+* `List`
+* `Tuple`
+* `Set`
+* `Dict`
+* `Union`
+* `Optional`
+* ...và các kiểu khác.
+
+////
+
+### Lớp như kiểu dữ liệu
+
+Bạn cũng có thể khai báo một lớp như là kiểu dữ liệu của một biến.
+
+Hãy nói rằng bạn muốn có một lớp `Person` với một tên:
+
+{* ../../docs_src/python_types/tutorial010.py hl[1:3] *}
+
+
+Sau đó bạn có thể khai báo một biến có kiểu là `Person`:
+
+{* ../../docs_src/python_types/tutorial010.py hl[6] *}
+
+
+Và lại một lần nữa, bạn có được tất cả sự hỗ trợ từ trình soạn thảo:
+
+

+
+Lưu ý rằng, điều này có nghĩa rằng "`one_person`" là một **thực thể** của lớp `Person`.
+
+Nó không có nghĩa "`one_person`" là một **lớp** gọi là `Person`.
+
+## Pydantic models
+
+
Pydantic là một thư viện Python để validate dữ liệu hiệu năng cao.
+
+Bạn có thể khai báo "hình dạng" của dữa liệu như là các lớp với các thuộc tính.
+
+Và mỗi thuộc tính có một kiểu dữ liệu.
+
+Sau đó bạn tạo một thực thể của lớp đó với một vài giá trị và nó sẽ validate các giá trị, chuyển đổi chúng sang kiểu dữ liệu phù hợp (nếu đó là trường hợp) và cho bạn một object với toàn bộ dữ liệu.
+
+Và bạn nhận được tất cả sự hỗ trợ của trình soạn thảo với object kết quả đó.
+
+Một ví dụ từ tài liệu chính thức của Pydantic:
+
+//// tab | Python 3.10+
+
+```Python
+{!> ../../docs_src/python_types/tutorial011_py310.py!}
+```
+
+////
+
+//// tab | Python 3.9+
+
+```Python
+{!> ../../docs_src/python_types/tutorial011_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python
+{!> ../../docs_src/python_types/tutorial011.py!}
+```
+
+////
+
+/// info
+
+Để học nhiều hơn về
Pydantic, tham khảo tài liệu của nó.
+
+///
+
+**FastAPI** được dựa hoàn toàn trên Pydantic.
+
+Bạn sẽ thấy nhiều ví dụ thực tế hơn trong [Hướng dẫn sử dụng](tutorial/index.md){.internal-link target=_blank}.
+
+/// tip
+
+Pydantic có một hành vi đặc biệt khi bạn sử dụng `Optional` hoặc `Union[Something, None]` mà không có giá trị mặc dịnh, bạn có thể đọc nhiều hơn về nó trong tài liệu của Pydantic về
Required Optional fields.
+
+///
+
+## Type Hints với Metadata Annotations
+
+Python cũng có một tính năng cho phép đặt **metadata bổ sung** trong những gợi ý kiểu dữ liệu này bằng cách sử dụng `Annotated`.
+
+//// tab | Python 3.9+
+
+Trong Python 3.9, `Annotated` là một phần của thư viện chuẩn, do đó bạn có thể import nó từ `typing`.
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial013_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+Ở phiên bản dưới Python 3.9, bạn import `Annotated` từ `typing_extensions`.
+
+Nó đã được cài đặt sẵng cùng với **FastAPI**.
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial013.py!}
+```
+
+////
+
+Python bản thân nó không làm bất kì điều gì với `Annotated`. Với các trình soạn thảo và các công cụ khác, kiểu dữ liệu vẫn là `str`.
+
+Nhưng bạn có thể sử dụng `Annotated` để cung cấp cho **FastAPI** metadata bổ sung về cách mà bạn muốn ứng dụng của bạn xử lí.
+
+Điều quan trọng cần nhớ là ***tham số kiểu dữ liệu* đầu tiên** bạn truyền tới `Annotated` là **kiểu giá trị thực sự**. Phần còn lại chỉ là metadata cho các công cụ khác.
+
+Bây giờ, bạn chỉ cần biết rằng `Annotated` tồn tại, và nó là tiêu chuẩn của Python. 😎
+
+
+Sau đó, bạn sẽ thấy sự **mạnh mẽ** mà nó có thể làm.
+
+/// tip
+
+Thực tế, cái này là **tiêu chuẩn của Python**, nghĩa là bạn vẫn sẽ có được **trải nghiệm phát triển tốt nhất có thể** với trình soạn thảo của bạn, với các công cụ bạn sử dụng để phân tích và tái cấu trúc code của bạn, etc. ✨
+
+Và code của bạn sẽ tương thích với nhiều công cụ và thư viện khác của Python. 🚀
+
+///
+
+## Các gợi ý kiểu dữ liệu trong **FastAPI**
+
+**FastAPI** lấy các ưu điểm của các gợi ý kiểu dữ liệu để thực hiện một số thứ.
+
+Với **FastAPI**, bạn khai báo các tham số với gợi ý kiểu và bạn có được:
+
+* **Sự hỗ trợ từ các trình soạn thảo**.
+* **Kiểm tra kiểu dữ liệu (type checking)**.
+
+...và **FastAPI** sử dụng các khia báo để:
+
+* **Định nghĩa các yêu cầu**: từ tham số đường dẫn của request, tham số query, headers, bodies, các phụ thuộc (dependencies),...
+* **Chuyển dổi dữ liệu*: từ request sang kiểu dữ liệu được yêu cầu.
+* **Kiểm tra tính đúng đắn của dữ liệu**: tới từ mỗi request:
+ * Sinh **lỗi tự động** để trả về máy khác khi dữ liệu không hợp lệ.
+* **Tài liệu hóa** API sử dụng OpenAPI:
+ * cái mà sau được được sử dụng bởi tài liệu tương tác người dùng.
+
+Điều này có thể nghe trừu tượng. Đừng lo lắng. Bạn sẽ thấy tất cả chúng trong [Hướng dẫn sử dụng](tutorial/index.md){.internal-link target=_blank}.
+
+Điều quan trọng là bằng việc sử dụng các kiểu dữ liệu chuẩn của Python (thay vì thêm các lớp, decorators,...), **FastAPI** sẽ thực hiện nhiều công việc cho bạn.
+
+/// info
+
+Nếu bạn đã đi qua toàn bộ các hướng dẫn và quay trở lại để tìm hiểu nhiều hơn về các kiểu dữ liệu, một tài nguyên tốt như
"cheat sheet" từ `mypy`.
+
+///
diff --git a/docs/vi/docs/tutorial/first-steps.md b/docs/vi/docs/tutorial/first-steps.md
new file mode 100644
index 000000000..901c8fd59
--- /dev/null
+++ b/docs/vi/docs/tutorial/first-steps.md
@@ -0,0 +1,335 @@
+# Những bước đầu tiên
+
+Tệp tin FastAPI đơn giản nhất có thể trông như này:
+
+{* ../../docs_src/first_steps/tutorial001.py *}
+
+Sao chép sang một tệp tin `main.py`.
+
+Chạy live server:
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [28720]
+INFO: Started server process [28722]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+/// note
+
+Câu lệnh `uvicorn main:app` được giải thích như sau:
+
+* `main`: tệp tin `main.py` (một Python "mô đun").
+* `app`: một object được tạo ra bên trong `main.py` với dòng `app = FastAPI()`.
+* `--reload`: làm server khởi động lại sau mỗi lần thay đổi. Chỉ sử dụng trong môi trường phát triển.
+
+///
+
+Trong output, có một dòng giống như:
+
+```hl_lines="4"
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+Dòng đó cho thấy URL, nơi mà app của bạn đang được chạy, trong máy local của bạn.
+
+### Kiểm tra
+
+Mở trình duyệt của bạn tại
http://127.0.0.1:8000.
+
+Bạn sẽ thấy một JSON response như:
+
+```JSON
+{"message": "Hello World"}
+```
+
+### Tài liệu tương tác API
+
+Bây giờ tới
http://127.0.0.1:8000/docs.
+
+Bạn sẽ thấy một tài liệu tương tác API (cung cấp bởi
Swagger UI):
+
+
+
+### Phiên bản thay thế của tài liệu API
+
+Và bây giờ tới
http://127.0.0.1:8000/redoc.
+
+Bạn sẽ thấy một bản thay thế của tài liệu (cung cấp bởi
ReDoc):
+
+
+
+### OpenAPI
+
+**FastAPI** sinh một "schema" với tất cả API của bạn sử dụng tiêu chuẩn **OpenAPI** cho định nghĩa các API.
+
+#### "Schema"
+
+Một "schema" là một định nghĩa hoặc mô tả thứ gì đó. Không phải code triển khai của nó, nhưng chỉ là một bản mô tả trừu tượng.
+
+#### API "schema"
+
+Trong trường hợp này,
OpenAPI là một bản mô tả bắt buộc cơ chế định nghĩa API của bạn.
+
+Định nghĩa cấu trúc này bao gồm những đường dẫn API của bạn, các tham số có thể có,...
+
+#### "Cấu trúc" dữ liệu
+
+Thuật ngữ "cấu trúc" (schema) cũng có thể được coi như là hình dạng của dữ liệu, tương tự như một JSON content.
+
+Trong trường hợp đó, nó có nghĩa là các thuộc tính JSON và các kiểu dữ liệu họ có,...
+
+#### OpenAPI và JSON Schema
+
+OpenAPI định nghĩa một cấu trúc API cho API của bạn. Và cấu trúc đó bao gồm các dịnh nghĩa (or "schema") về dữ liệu được gửi đi và nhận về bởi API của bạn, sử dụng **JSON Schema**, một tiêu chuẩn cho cấu trúc dữ liệu JSON.
+
+#### Kiểm tra `openapi.json`
+
+Nếu bạn tò mò về việc cấu trúc OpenAPI nhìn như thế nào thì FastAPI tự động sinh một JSON (schema) với các mô tả cho tất cả API của bạn.
+
+Bạn có thể thấy nó trực tiếp tại:
http://127.0.0.1:8000/openapi.json.
+
+Nó sẽ cho thấy một JSON bắt đầu giống như:
+
+```JSON
+{
+ "openapi": "3.1.0",
+ "info": {
+ "title": "FastAPI",
+ "version": "0.1.0"
+ },
+ "paths": {
+ "/items/": {
+ "get": {
+ "responses": {
+ "200": {
+ "description": "Successful Response",
+ "content": {
+ "application/json": {
+
+
+
+...
+```
+
+#### OpenAPI dùng để làm gì?
+
+Cấu trúc OpenAPI là sức mạnh của tài liệu tương tác.
+
+Và có hàng tá các bản thay thế, tất cả đều dựa trên OpenAPI. Bạn có thể dễ dàng thêm bất kì bản thay thế bào cho ứng dụng của bạn được xây dựng với **FastAPI**.
+
+Bạn cũng có thể sử dụng nó để sinh code tự động, với các client giao viết qua API của bạn. Ví dụ, frontend, mobile hoặc các ứng dụng IoT.
+
+## Tóm lại, từng bước một
+
+### Bước 1: import `FastAPI`
+
+{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
+
+`FastAPI` là một Python class cung cấp tất cả chức năng cho API của bạn.
+
+/// note | Chi tiết kĩ thuật
+
+`FastAPI` là một class kế thừa trực tiếp `Starlette`.
+
+Bạn cũng có thể sử dụng tất cả
Starlette chức năng với `FastAPI`.
+
+///
+
+### Bước 2: Tạo một `FastAPI` "instance"
+
+{* ../../docs_src/first_steps/tutorial001.py hl[3] *}
+
+Biến `app` này là một "instance" của class `FastAPI`.
+
+Đây sẽ là điểm cốt lõi để tạo ra tất cả API của bạn.
+
+`app` này chính là điều được nhắc tới bởi `uvicorn` trong câu lệnh:
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+
+
+Nếu bạn tạo ứng dụng của bạn giống như:
+
+{* ../../docs_src/first_steps/tutorial002.py hl[3] *}
+
+Và đặt nó trong một tệp tin `main.py`, sau đó bạn sẽ gọi `uvicorn` giống như:
+
+
+
+```console
+$ uvicorn main:my_awesome_api --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+
+
+### Bước 3: tạo một *đường dẫn toán tử*
+
+#### Đường dẫn
+
+"Đường dẫn" ở đây được nhắc tới là phần cuối cùng của URL bắt đầu từ `/`.
+
+Do đó, trong một URL nhìn giống như:
+
+```
+https://example.com/items/foo
+```
+
+...đường dẫn sẽ là:
+
+```
+/items/foo
+```
+
+/// info
+
+Một đường dẫn cũng là một cách gọi chung cho một "endpoint" hoặc một "route".
+
+///
+
+Trong khi xây dựng một API, "đường dẫn" là các chính để phân tách "mối quan hệ" và "tài nguyên".
+
+#### Toán tử (Operation)
+
+"Toán tử" ở đây được nhắc tới là một trong các "phương thức" HTTP.
+
+Một trong những:
+
+* `POST`
+* `GET`
+* `PUT`
+* `DELETE`
+
+...và một trong những cái còn lại:
+
+* `OPTIONS`
+* `HEAD`
+* `PATCH`
+* `TRACE`
+
+Trong giao thức HTTP, bạn có thể giao tiếp trong mỗi đường dẫn sử dụng một (hoặc nhiều) trong các "phương thức này".
+
+---
+
+Khi xây dựng các API, bạn thường sử dụng cụ thể các phương thức HTTP này để thực hiện một hành động cụ thể.
+
+Thông thường, bạn sử dụng
+
+* `POST`: để tạo dữ liệu.
+* `GET`: để đọc dữ liệu.
+* `PUT`: để cập nhật dữ liệu.
+* `DELETE`: để xóa dữ liệu.
+
+Do đó, trong OpenAPI, mỗi phương thức HTTP được gọi là một "toán tử (operation)".
+
+Chúng ta cũng sẽ gọi chúng là "**các toán tử**".
+
+#### Định nghĩa moojt *decorator cho đường dẫn toán tử*
+
+{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
+
+`@app.get("/")` nói **FastAPI** rằng hàm bên dưới có trách nhiệm xử lí request tới:
+
+* đường dẫn `/`
+* sử dụng một
toán tửget
+
+/// info | Thông tin về "`@decorator`"
+
+Cú pháp `@something` trong Python được gọi là một "decorator".
+
+Bạn đặt nó trên một hàm. Giống như một chiếc mũ xinh xắn (Tôi ddonas đó là lí do mà thuật ngữ này ra đời).
+
+Một "decorator" lấy một hàm bên dưới và thực hiện một vài thứ với nó.
+
+Trong trường hợp của chúng ta, decorator này nói **FastAPI** rằng hàm bên dưới ứng với **đường dẫn** `/` và một **toán tử** `get`.
+
+Nó là một "**decorator đường dẫn toán tử**".
+
+///
+
+Bạn cũng có thể sử dụng với các toán tử khác:
+
+* `@app.post()`
+* `@app.put()`
+* `@app.delete()`
+
+Và nhiều hơn với các toán tử còn lại:
+
+* `@app.options()`
+* `@app.head()`
+* `@app.patch()`
+* `@app.trace()`
+
+/// tip
+
+Bạn thoải mái sử dụng mỗi toán tử (phương thức HTTP) như bạn mơ ước.
+
+**FastAPI** không bắt buộc bất kì ý nghĩa cụ thể nào.
+
+Thông tin ở đây được biểu thị như là một chỉ dẫn, không phải là một yêu cầu bắt buộc.
+
+Ví dụ, khi sử dụng GraphQL bạn thông thường thực hiện tất cả các hành động chỉ bằng việc sử dụng các toán tử `POST`.
+
+///
+
+### Step 4: Định nghĩa **hàm cho đường dẫn toán tử**
+
+Đây là "**hàm cho đường dẫn toán tử**":
+
+* **đường dẫn**: là `/`.
+* **toán tử**: là `get`.
+* **hàm**: là hàm bên dưới "decorator" (bên dưới `@app.get("/")`).
+
+{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
+
+Đây là một hàm Python.
+
+Nó sẽ được gọi bởi **FastAPI** bất cứ khi nào nó nhận một request tới URL "`/`" sử dụng một toán tử `GET`.
+
+Trong trường hợp này, nó là một hàm `async`.
+
+---
+
+Bạn cũng có thể định nghĩa nó như là một hàm thông thường thay cho `async def`:
+
+{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
+
+/// note
+
+Nếu bạn không biết sự khác nhau, kiểm tra [Async: *"Trong khi vội vàng?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
+
+///
+
+### Bước 5: Nội dung trả về
+
+{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
+
+Bạn có thể trả về một `dict`, `list`, một trong những giá trị đơn như `str`, `int`,...
+
+Bạn cũng có thể trả về Pydantic model (bạn sẽ thấy nhiều hơn về nó sau).
+
+Có nhiều object và model khác nhau sẽ được tự động chuyển đổi sang JSON (bao gồm cả ORM,...). Thử sử dụng loại ưa thích của bạn, nó có khả năng cao đã được hỗ trợ.
+
+## Tóm lại
+
+* Import `FastAPI`.
+* Tạo một `app` instance.
+* Viết một **decorator cho đường dẫn toán tử** (giống như `@app.get("/")`).
+* Viết một **hàm cho đường dẫn toán tử** (giống như `def root(): ...` ở trên).
+* Chạy server trong môi trường phát triển (giống như `uvicorn main:app --reload`).
diff --git a/docs/vi/docs/tutorial/index.md b/docs/vi/docs/tutorial/index.md
new file mode 100644
index 000000000..dfeeed8c5
--- /dev/null
+++ b/docs/vi/docs/tutorial/index.md
@@ -0,0 +1,83 @@
+# Hướng dẫn sử dụng
+
+Hướng dẫn này cho bạn thấy từng bước cách sử dụng **FastAPI** đa số các tính năng của nó.
+
+Mỗi phần được xây dựng từ những phần trước đó, nhưng nó được cấu trúc thành các chủ đề riêng biệt, do đó bạn có thể xem trực tiếp từng phần cụ thể bất kì để giải quyết những API cụ thể mà bạn cần.
+
+Nó cũng được xây dựng để làm việc như một tham chiếu trong tương lai.
+
+Do đó bạn có thể quay lại và tìm chính xác những gì bạn cần.
+
+## Chạy mã
+
+Tất cả các code block có thể được sao chép và sử dụng trực tiếp (chúng thực chất là các tệp tin Python đã được kiểm thử).
+
+Để chạy bất kì ví dụ nào, sao chép code tới tệp tin `main.py`, và bắt đầu `uvicorn` với:
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [28720]
+INFO: Started server process [28722]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+**Khuyến khích** bạn viết hoặc sao chép code, sửa và chạy nó ở local.
+
+Sử dụng nó trong trình soạn thảo của bạn thực sự cho bạn thấy những lợi ích của FastAPI, thấy được cách bạn viết code ít hơn, tất cả đều được type check, autocompletion,...
+
+---
+
+## Cài đặt FastAPI
+
+Bước đầu tiên là cài đặt FastAPI.
+
+Với hướng dẫn này, bạn có thể muốn cài đặt nó với tất cả các phụ thuộc và tính năng tùy chọn:
+
+
+
+```console
+$ pip install "fastapi[all]"
+
+---> 100%
+```
+
+
+
+...dó cũng bao gồm `uvicorn`, bạn có thể sử dụng như một server để chạy code của bạn.
+
+/// note
+
+Bạn cũng có thể cài đặt nó từng phần.
+
+Đây là những gì bạn có thể sẽ làm một lần duy nhất bạn muốn triển khai ứng dụng của bạn lên production:
+
+```
+pip install fastapi
+```
+
+Cũng cài đặt `uvicorn` để làm việc như một server:
+
+```
+pip install "uvicorn[standard]"
+```
+
+Và tương tự với từng phụ thuộc tùy chọn mà bạn muốn sử dụng.
+
+///
+
+## Hướng dẫn nâng cao
+
+Cũng có một **Hướng dẫn nâng cao** mà bạn có thể đọc nó sau **Hướng dẫn sử dụng**.
+
+**Hướng dẫn sử dụng nâng cao**, xây dựng dựa trên cái này, sử dụng các khái niệm tương tự, và dạy bạn những tính năng mở rộng.
+
+Nhưng bạn nên đọc **Hướng dẫn sử dụng** đầu tiên (những gì bạn đang đọc).
+
+Nó được thiết kế do đó bạn có thể xây dựng một ứng dụng hoàn chỉnh chỉ với **Hướng dẫn sử dụng**, và sau đó mở rộng nó theo các cách khác nhau, phụ thuộc vào những gì bạn cần, sử dụng một vài ý tưởng bổ sung từ **Hướng dẫn sử dụng nâng cao**.
diff --git a/docs/vi/docs/tutorial/static-files.md b/docs/vi/docs/tutorial/static-files.md
new file mode 100644
index 000000000..ecf8c2485
--- /dev/null
+++ b/docs/vi/docs/tutorial/static-files.md
@@ -0,0 +1,40 @@
+# Tệp tĩnh (Static Files)
+
+Bạn có thể triển khai tệp tĩnh tự động từ một thư mục bằng cách sử dụng StaticFiles.
+
+## Sử dụng `Tệp tĩnh`
+
+- Nhập `StaticFiles`.
+- "Mount" a `StaticFiles()` instance in a specific path.
+
+{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
+
+/// note | Chi tiết kỹ thuật
+
+Bạn cũng có thể sử dụng `from starlette.staticfiles import StaticFiles`.
+
+**FastAPI** cung cấp cùng `starlette.staticfiles` như `fastapi.staticfiles` giúp đơn giản hóa việc sử dụng, nhưng nó thực sự đến từ Starlette.
+
+///
+
+### "Mounting" là gì
+
+"Mounting" có nghĩa là thêm một ứng dụng "độc lập" hoàn chỉnh vào một đường dẫn cụ thể, sau đó ứng dụng đó sẽ chịu trách nhiệm xử lý tất cả các đường dẫn con.
+
+Điều này khác với việc sử dụng `APIRouter` vì một ứng dụng được gắn kết là hoàn toàn độc lập. OpenAPI và tài liệu từ ứng dụng chính của bạn sẽ không bao gồm bất kỳ thứ gì từ ứng dụng được gắn kết, v.v.
+
+Bạn có thể đọc thêm về điều này trong [Hướng dẫn Người dùng Nâng cao](../advanced/index.md){.internal-link target=\_blank}.
+
+## Chi tiết
+
+Đường dẫn đầu tiên `"/static"` là đường dẫn con mà "ứng dụng con" này sẽ được "gắn" vào. Vì vậy, bất kỳ đường dẫn nào bắt đầu bằng `"/static"` sẽ được xử lý bởi nó.
+
+Đường dẫn `directory="static"` là tên của thư mục chứa tệp tĩnh của bạn.
+
+Tham số `name="static"` đặt tên cho nó để có thể được sử dụng bên trong **FastAPI**.
+
+Tất cả các tham số này có thể khác với `static`, điều chỉnh chúng với phù hợp với ứng dụng của bạn.
+
+## Thông tin thêm
+
+Để biết thêm chi tiết và tùy chọn, hãy xem
Starlette's docs about Static Files.
diff --git a/docs/vi/docs/virtual-environments.md b/docs/vi/docs/virtual-environments.md
new file mode 100644
index 000000000..22d8e153e
--- /dev/null
+++ b/docs/vi/docs/virtual-environments.md
@@ -0,0 +1,842 @@
+# Môi trường ảo (Virtual Environments)
+
+Khi bạn làm việc trong các dự án Python, bạn có thể sử dụng một **môi trường ảo** (hoặc một cơ chế tương tự) để cách ly các gói bạn cài đặt cho mỗi dự án.
+
+/// info
+Nếu bạn đã biết về các môi trường ảo, cách tạo chúng và sử dụng chúng, bạn có thể bỏ qua phần này. 🤓
+
+///
+
+/// tip
+
+Một **môi trường ảo** khác với một **biến môi trường (environment variable)**.
+
+Một **biến môi trường** là một biến trong hệ thống có thể được sử dụng bởi các chương trình.
+
+Một **môi trường ảo** là một thư mục với một số tệp trong đó.
+
+///
+
+/// info
+
+Trang này sẽ hướng dẫn bạn cách sử dụng các **môi trường ảo** và cách chúng hoạt động.
+
+Nếu bạn đã sẵn sàng sử dụng một **công cụ có thể quản lý tất cả mọi thứ** cho bạn (bao gồm cả việc cài đặt Python), hãy thử
uv.
+
+///
+
+## Tạo một Dự án
+
+Đầu tiên, tạo một thư mục cho dự án của bạn.
+
+Cách tôi thường làm là tạo một thư mục có tên `code` trong thư mục `home/user`.
+
+Và trong thư mục đó, tôi tạo một thư mục cho mỗi dự án.
+
+
+
+```console
+// Đi đến thư mục home
+$ cd
+// Tạo một thư mục cho tất cả các dự án của bạn
+$ mkdir code
+// Vào thư mục code
+$ cd code
+// Tạo một thư mục cho dự án này
+$ mkdir awesome-project
+// Vào thư mục dự án
+$ cd awesome-project
+```
+
+
+
+## Tạo một Môi trường ảo
+
+Khi bạn bắt đầu làm việc với một dự án Python **trong lần đầu**, hãy tạo một môi trường ảo **
trong thư mục dự án của bạn**.
+
+/// tip
+
+Bạn cần làm điều này **một lần cho mỗi dự án**, không phải mỗi khi bạn làm việc.
+///
+
+//// tab | `venv`
+
+Để tạo một môi trường ảo, bạn có thể sử dụng module `venv` có sẵn của Python.
+
+
+
+```console
+$ python -m venv .venv
+```
+
+
+
+/// details | Cách các lệnh hoạt động
+
+* `python`: sử dụng chương trình `python`
+* `-m`: gọi một module như một script, chúng ta sẽ nói về module đó sau
+* `venv`: sử dụng module `venv` được cài đặt sẵn của Python
+* `.venv`: tạo môi trường ảo trong thư mục mới `.venv`
+
+///
+
+////
+
+//// tab | `uv`
+
+Nếu bạn có
`uv` được cài đặt, bạn có thể sử dụng nó để tạo một môi trường ảo.
+
+
+
+```console
+$ uv venv
+```
+
+
+
+/// tip
+
+Mặc định, `uv` sẽ tạo một môi trường ảo trong một thư mục có tên `.venv`.
+
+Nhưng bạn có thể tùy chỉnh nó bằng cách thêm một đối số với tên thư mục.
+
+///
+
+////
+
+Lệnh này tạo một môi trường ảo mới trong một thư mục có tên `.venv`.
+
+/// details | `.venv` hoặc tên khác
+
+Bạn có thể tạo môi trường ảo trong một thư mục khác, nhưng thường người ta quy ước đặt nó là `.venv`.
+
+///
+
+## Kích hoạt Môi trường ảo
+
+Kích hoạt môi trường ảo mới để bất kỳ lệnh Python nào bạn chạy hoặc gói nào bạn cài đặt sẽ sử dụng nó.
+
+/// tip
+
+Làm điều này **mỗi khi** bạn bắt đầu một **phiên terminal mới** để làm việc trên dự án.
+
+///
+
+//// tab | Linux, macOS
+
+
+
+```console
+$ source .venv/bin/activate
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ .venv\Scripts\Activate.ps1
+```
+
+
+
+////
+
+//// tab | Windows Bash
+
+Nếu bạn sử dụng Bash cho Windows (ví dụ:
Git Bash):
+
+
+
+```console
+$ source .venv/Scripts/activate
+```
+
+
+
+////
+
+/// tip
+
+Mỗi khi bạn cài đặt thêm một **package mới** trong môi trường đó, hãy **kích hoạt** môi trường đó lại.
+
+Điều này đảm bảo rằng khi bạn sử dụng một **chương trình dòng lệnh (
CLI)** được cài đặt từ gói đó, bạn sẽ dùng bản cài đặt từ môi trường ảo của mình thay vì bản được cài đặt toàn cục khác có thể có phiên bản khác với phiên bản bạn cần.
+
+///
+
+## Kiểm tra xem Môi trường ảo đã được Kích hoạt chưa
+
+Kiểm tra xem môi trường ảo đã được kích hoạt chưa (lệnh trước đó đã hoạt động).
+
+/// tip
+
+Điều này là **không bắt buộc**, nhưng nó là một cách tốt để **kiểm tra** rằng mọi thứ đang hoạt động như mong đợi và bạn đang sử dụng đúng môi trường ảo mà bạn đã định.
+
+///
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+
+
+Nếu nó hiển thị `python` binary tại `.venv/bin/python`, trong dự án của bạn (trong trường hợp `awesome-project`), thì tức là nó hoạt động. 🎉
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ Get-Command python
+
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+
+
+Nếu nó hiển thị `python` binary tại `.venv\Scripts\python`, trong dự án của bạn (trong trường hợp `awesome-project`), thì tức là nó hoạt động. 🎉
+
+////
+
+## Nâng cấp `pip`
+
+/// tip
+
+Nếu bạn sử dụng
`uv` bạn sử dụng nó để cài đặt thay vì `pip`, thì bạn không cần cập nhật `pip`. 😎
+
+///
+
+Nếu bạn sử dụng `pip` để cài đặt gói (nó được cài đặt mặc định với Python), bạn nên **nâng cấp** nó lên phiên bản mới nhất.
+
+Nhiều lỗi khác nhau trong khi cài đặt gói được giải quyết chỉ bằng cách nâng cấp `pip` trước.
+
+/// tip
+
+Bạn thường làm điều này **một lần**, ngay sau khi bạn tạo môi trường ảo.
+
+///
+
+Đảm bảo rằng môi trường ảo đã được kích hoạt (với lệnh trên) và sau đó chạy:
+
+
+
+```console
+$ python -m pip install --upgrade pip
+
+---> 100%
+```
+
+
+
+## Thêm `.gitignore`
+
+Nếu bạn sử dụng **Git** (nên làm), hãy thêm một file `.gitignore` để Git bỏ qua mọi thứ trong `.venv`.
+
+/// tip
+
+Nếu bạn sử dụng
`uv` để tạo môi trường ảo, nó đã tự động làm điều này cho bạn, bạn có thể bỏ qua bước này. 😎
+
+///
+
+/// tip
+
+Làm điều này **một lần**, ngay sau khi bạn tạo môi trường ảo.
+
+///
+
+
+
+```console
+$ echo "*" > .venv/.gitignore
+```
+
+
+
+/// details | Cách lệnh hoạt động
+
+* `echo "*"`: sẽ "in" văn bản `*` trong terminal (phần tiếp theo sẽ thay đổi điều đó một chút)
+* `>`: bất kỳ văn bản nào được in ra terminal bởi lệnh trước `>` không được in ra mà thay vào đó được viết vào file ở phía bên phải của `>`
+* `.gitignore`: tên của file mà văn bản sẽ được viết vào
+
+Và `*` với Git có nghĩa là "mọi thứ". Vì vậy, nó sẽ bỏ qua mọi thứ trong thư mục `.venv`.
+
+Lệnh này sẽ tạo một file `.gitignore` với nội dung:
+
+```gitignore
+*
+```
+
+///
+
+## Cài đặt gói (packages)
+
+Sau khi kích hoạt môi trường, bạn có thể cài đặt các gói trong đó.
+
+/// tip
+
+Thực hiện điều này **một lần** khi cài đặt hoặc cập nhật gói cần thiết cho dự án của bạn.
+
+Nếu bạn cần cập nhật phiên bản hoặc thêm một gói mới, bạn sẽ **thực hiện điều này lại**.
+
+///
+
+### Cài đặt gói trực tiếp
+
+Nếu bạn cần cập nhật phiên bản hoặc thêm một gói mới, bạn sẽ **thực hiện điều này lại**.
+
+/// tip
+Để quản lý dự án tốt hơn, hãy liệt kê tất cả các gói và phiên bản cần thiết trong một file (ví dụ `requirements.txt` hoặc `pyproject.toml`).
+
+///
+
+//// tab | `pip`
+
+
+
+```console
+$ pip install "fastapi[standard]"
+
+---> 100%
+```
+
+
+
+////
+
+//// tab | `uv`
+
+Nếu bạn có
`uv`:
+
+
+
+```console
+$ uv pip install "fastapi[standard]"
+---> 100%
+```
+
+
+
+////
+
+### Cài đặt từ `requirements.txt`
+
+Nếu bạn có một tệp `requirements.txt`, bạn có thể sử dụng nó để cài đặt các gói.
+
+//// tab | `pip`
+
+
+
+```console
+$ pip install -r requirements.txt
+---> 100%
+```
+
+
+
+////
+
+//// tab | `uv`
+
+Nếu bạn có
`uv`:
+
+
+
+```console
+$ uv pip install -r requirements.txt
+---> 100%
+```
+
+
+
+////
+
+/// details | `requirements.txt`
+
+Một tệp `requirements.txt` với một số gói sẽ trông như thế này:
+
+```requirements.txt
+fastapi[standard]==0.113.0
+pydantic==2.8.0
+```
+
+///
+
+## Chạy Chương trình của bạn
+
+Sau khi kích hoạt môi trường ảo, bạn có thể chạy chương trình của mình, nó sẽ sử dụng Python trong môi trường ảo của bạn với các gói bạn đã cài đặt.
+
+
+
+```console
+$ python main.py
+
+Hello World
+```
+
+
+
+## Cấu hình Trình soạn thảo của bạn
+
+Nếu bạn sử dụng một trình soạn thảo, hãy đảm bảo bạn cấu hình nó để sử dụng cùng môi trường ảo mà bạn đã tạo (trình soạn thảo sẽ tự động phát hiện môi trường ảo) để bạn có thể nhận được tính năng tự động hoàn thành câu lệnh (autocomplete) và in lỗi trực tiếp trong trình soạn thảo (inline errors).
+
+Ví dụ:
+
+*
VS Code
+*
PyCharm
+
+/// tip
+
+Bạn thường chỉ cần làm điều này **một lần**, khi bạn tạo môi trường ảo.
+
+///
+
+## Huỷ kích hoạt Môi trường ảo
+
+Khi bạn hoàn tất việc làm trên dự án của bạn, bạn có thể **huỷ kích hoạt** môi trường ảo.
+
+
+
+```console
+$ deactivate
+```
+
+
+
+Như vậy, khi bạn chạy `python`, nó sẽ không chạy từ môi trường ảo đó với các gói đã cài đặt.
+
+## Sẵn sàng để Làm việc
+
+Bây giờ bạn đã sẵn sàng để làm việc trên dự án của mình rồi đấy.
+
+/// tip
+
+Bạn muốn hiểu tất cả những gì ở trên?
+
+Tiếp tục đọc. 👇🤓
+
+///
+
+## Tại sao cần Môi trường ảo
+
+Để làm việc với FastAPI, bạn cần cài đặt
Python.
+
+Sau đó, bạn sẽ cần **cài đặt** FastAPI và bất kỳ **gói** nào mà bạn muốn sử dụng.
+
+Để cài đặt gói, bạn thường sử dụng lệnh `pip` có sẵn với Python (hoặc các phiên bản tương tự).
+
+Tuy nhiên, nếu bạn sử dụng `pip` trực tiếp, các gói sẽ được cài đặt trong **môi trường Python toàn cục** của bạn (phần cài đặt toàn cục của Python).
+
+### Vấn đề
+
+Vậy, vấn đề gì khi cài đặt gói trong môi trường Python toàn cục?
+
+Trong một vài thời điểm, bạn sẽ phải viết nhiều chương trình khác nhau phụ thuộc vào **các gói khác nhau**. Và một số dự án bạn thực hiện lại phụ thuộc vào **các phiên bản khác nhau** của cùng một gói. 😱
+
+Ví dụ, bạn có thể tạo một dự án được gọi là `philosophers-stone`, chương trình này phụ thuộc vào một gói khác được gọi là **`harry`, sử dụng phiên bản `1`**. Vì vậy, bạn cần cài đặt `harry`.
+
+```mermaid
+flowchart LR
+ stone(philosophers-stone) -->|phụ thuộc| harry-1[harry v1]
+```
+
+Sau đó, vào một vài thời điểm sau, bạn tạo một dự án khác được gọi là `prisoner-of-azkaban`, và dự án này cũng phụ thuộc vào `harry`, nhưng dự án này cần **`harry` phiên bản `3`**.
+
+```mermaid
+flowchart LR
+ azkaban(prisoner-of-azkaban) --> |phụ thuộc| harry-3[harry v3]
+```
+
+Bây giờ, vấn đề là, nếu bạn cài đặt các gói toàn cục (trong môi trường toàn cục) thay vì trong một **môi trường ảo cục bộ**, bạn sẽ phải chọn phiên bản `harry` nào để cài đặt.
+
+Nếu bạn muốn chạy `philosophers-stone` bạn sẽ cần phải cài đặt `harry` phiên bản `1`, ví dụ với:
+
+
+
+```console
+$ pip install "harry==1"
+```
+
+
+
+Và sau đó bạn sẽ có `harry` phiên bản `1` được cài đặt trong môi trường Python toàn cục của bạn.
+
+```mermaid
+flowchart LR
+ subgraph global[môi trường toàn cục]
+ harry-1[harry v1]
+ end
+ subgraph stone-project[dự án philosophers-stone ]
+ stone(philosophers-stone) -->|phụ thuộc| harry-1
+ end
+```
+
+Nhưng sau đó, nếu bạn muốn chạy `prisoner-of-azkaban`, bạn sẽ cần phải gỡ bỏ `harry` phiên bản `1` và cài đặt `harry` phiên bản `3` (hoặc chỉ cần cài đặt phiên bản `3` sẽ tự động gỡ bỏ phiên bản `1`).
+
+
+
+```console
+$ pip install "harry==3"
+```
+
+
+
+Và sau đó bạn sẽ có `harry` phiên bản `3` được cài đặt trong môi trường Python toàn cục của bạn.
+
+Và nếu bạn cố gắng chạy `philosophers-stone` lại, có khả năng nó sẽ **không hoạt động** vì nó cần `harry` phiên bản `1`.
+
+```mermaid
+flowchart LR
+ subgraph global[môi trường toàn cục]
+ harry-1[
harry v1]
+ style harry-1 fill:#ccc,stroke-dasharray: 5 5
+ harry-3[harry v3]
+ end
+ subgraph stone-project[dự án philosophers-stone ]
+ stone(philosophers-stone) -.-x|⛔️| harry-1
+ end
+ subgraph azkaban-project[dự án prisoner-of-azkaban ]
+ azkaban(prisoner-of-azkaban) --> |phụ thuộc| harry-3
+ end
+```
+
+/// tip
+
+Mặc dù các gói Python thường cố gắng **tránh các thay đổi làm hỏng code** trong **phiên bản mới**, nhưng để đảm bảo an toàn, bạn nên chủ động cài đặt phiên bản mới và chạy kiểm thử để xác nhận mọi thứ vẫn hoạt động đúng.
+
+///
+
+Bây giờ, hãy hình dung về **nhiều** gói khác nhau mà tất cả các dự án của bạn phụ thuộc vào. Rõ ràng rất khó để quản lý. Điều này dẫn tới việc là bạn sẽ có nhiều dự án với **các phiên bản không tương thích** của các gói, và bạn có thể không biết tại sao một số thứ không hoạt động.
+
+Hơn nữa, tuỳ vào hệ điều hành của bạn (vd Linux, Windows, macOS), có thể đã có Python được cài đặt sẵn. Trong trường hợp ấy, một vài gói nhiều khả năng đã được cài đặt trước với các phiên bản **cần thiết cho hệ thống của bạn**. Nếu bạn cài đặt các gói trong môi trường Python toàn cục, bạn có thể sẽ **phá vỡ** một số chương trình đã được cài đặt sẵn cùng hệ thống.
+
+## Nơi các Gói được Cài đặt
+
+Khi bạn cài đặt Python, nó sẽ tạo ra một vài thư mục và tệp trong máy tính của bạn.
+
+Một vài thư mục này là những thư mục chịu trách nhiệm có tất cả các gói bạn cài đặt.
+
+Khi bạn chạy:
+
+
+
+```console
+// Đừng chạy lệnh này ngay, đây chỉ là một ví dụ 🤓
+$ pip install "fastapi[standard]"
+---> 100%
+```
+
+
+
+Lệnh này sẽ tải xuống một tệp nén với mã nguồn FastAPI, thường là từ
PyPI.
+
+Nó cũng sẽ **tải xuống** các tệp cho các gói khác mà FastAPI phụ thuộc vào.
+
+Sau đó, nó sẽ **giải nén** tất cả các tệp đó và đưa chúng vào một thư mục trong máy tính của bạn.
+
+Mặc định, nó sẽ đưa các tệp đã tải xuống và giải nén vào thư mục được cài đặt cùng Python của bạn, đó là **môi trường toàn cục**.
+
+## Những Môi trường ảo là gì?
+
+Cách giải quyết cho vấn đề có tất cả các gói trong môi trường toàn cục là sử dụng một **môi trường ảo cho mỗi dự án** bạn làm việc.
+
+Một môi trường ảo là một **thư mục**, rất giống với môi trường toàn cục, trong đó bạn có thể cài đặt các gói cho một dự án.
+
+Vì vậy, mỗi dự án sẽ có một môi trường ảo riêng của nó (thư mục `.venv`) với các gói riêng của nó.
+
+```mermaid
+flowchart TB
+ subgraph stone-project[dự án philosophers-stone ]
+ stone(philosophers-stone) --->|phụ thuộc| harry-1
+ subgraph venv1[.venv]
+ harry-1[harry v1]
+ end
+ end
+ subgraph azkaban-project[dự án prisoner-of-azkaban ]
+ azkaban(prisoner-of-azkaban) --->|phụ thuộc| harry-3
+ subgraph venv2[.venv]
+ harry-3[harry v3]
+ end
+ end
+ stone-project ~~~ azkaban-project
+```
+
+## Kích hoạt Môi trường ảo nghĩa là gì
+
+Khi bạn kích hoạt một môi trường ảo, ví dụ với:
+
+//// tab | Linux, macOS
+
+
+
+```console
+$ source .venv/bin/activate
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ .venv\Scripts\Activate.ps1
+```
+
+
+
+////
+
+//// tab | Windows Bash
+
+Nếu bạn sử dụng Bash cho Windows (ví dụ
Git Bash):
+
+
+
+```console
+$ source .venv/Scripts/activate
+```
+
+
+
+////
+
+Lệnh này sẽ tạo hoặc sửa đổi một số [biến môi trường](environment-variables.md){.internal-link target=_blank} mà sẽ được sử dụng cho các lệnh tiếp theo.
+
+Một trong số đó là biến `PATH`.
+
+/// tip
+
+Bạn có thể tìm hiểu thêm về biến `PATH` trong [Biến môi trường](environment-variables.md#path-environment-variable){.internal-link target=_blank} section.
+
+///
+
+Kích hoạt môi trường ảo thêm đường dẫn `.venv/bin` (trên Linux và macOS) hoặc `.venv\Scripts` (trên Windows) vào biến `PATH`.
+
+Giả sử rằng trước khi kích hoạt môi trường, biến `PATH` như sau:
+
+//// tab | Linux, macOS
+
+```plaintext
+/usr/bin:/bin:/usr/sbin:/sbin
+```
+
+Nghĩa là hệ thống sẽ tìm kiếm chương trình trong:
+
+* `/usr/bin`
+* `/bin`
+* `/usr/sbin`
+* `/sbin`
+
+////
+
+//// tab | Windows
+
+```plaintext
+C:\Windows\System32
+```
+
+Nghĩa là hệ thống sẽ tìm kiếm chương trình trong:
+
+* `C:\Windows\System32`
+
+////
+
+Sau khi kích hoạt môi trường ảo, biến `PATH` sẽ như sau:
+
+//// tab | Linux, macOS
+
+```plaintext
+/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin
+```
+
+Nghĩa là hệ thống sẽ bắt đầu tìm kiếm chương trình trong:
+
+```plaintext
+/home/user/code/awesome-project/.venv/bin
+```
+
+trước khi tìm kiếm trong các thư mục khác.
+
+Vì vậy, khi bạn gõ `python` trong terminal, hệ thống sẽ tìm thấy chương trình Python trong:
+
+```plaintext
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+và sử dụng chương trình đó.
+
+////
+
+//// tab | Windows
+
+```plaintext
+C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32
+```
+
+Nghĩa là hệ thống sẽ bắt đầu tìm kiếm chương trình trong:
+
+```plaintext
+C:\Users\user\code\awesome-project\.venv\Scripts
+```
+
+trước khi tìm kiếm trong các thư mục khác.
+
+Vì vậy, khi bạn gõ `python` trong terminal, hệ thống sẽ tìm thấy chương trình Python trong:
+
+```plaintext
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+và sử dụng chương trình đó.
+
+////
+
+Một chi tiết quan trọng là nó sẽ đưa địa chỉ của môi trường ảo vào **đầu** của biến `PATH`. Hệ thống sẽ tìm kiếm nó **trước** khi tìm kiếm bất kỳ Python nào khác có sẵn. Vì vậy, khi bạn chạy `python`, nó sẽ sử dụng Python **từ môi trường ảo** thay vì bất kỳ Python nào khác (ví dụ, Python từ môi trường toàn cục).
+
+Kích hoạt một môi trường ảo cũng thay đổi một vài thứ khác, nhưng đây là một trong những điều quan trọng nhất mà nó thực hiện.
+
+## Kiểm tra một Môi trường ảo
+
+Khi bạn kiểm tra một môi trường ảo đã được kích hoạt chưa, ví dụ với:
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ Get-Command python
+
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+
+
+////
+
+
+Điều đó có nghĩa là chương trình `python` sẽ được sử dụng là chương trình **trong môi trường ảo**.
+
+Bạn sử dụng `which` trên Linux và macOS và `Get-Command` trên Windows PowerShell.
+
+Cách hoạt động của lệnh này là nó sẽ đi và kiểm tra biến `PATH`, đi qua **mỗi đường dẫn theo thứ tự**, tìm kiếm chương trình được gọi là `python`. Khi nó tìm thấy nó, nó sẽ **hiển thị cho bạn đường dẫn** đến chương trình đó.
+
+Điều quan trọng nhất là khi bạn gọi `python`, đó chính là chương trình `python` được thực thi.
+
+Vì vậy, bạn có thể xác nhận nếu bạn đang ở trong môi trường ảo đúng.
+
+/// tip
+
+Dễ dàng kích hoạt một môi trường ảo, cài đặt Python, và sau đó **chuyển đến một dự án khác**.
+
+Và dự án thứ hai **sẽ không hoạt động** vì bạn đang sử dụng **Python không đúng**, từ một môi trường ảo cho một dự án khác.
+
+Thật tiện lợi khi có thể kiểm tra `python` nào đang được sử dụng 🤓
+
+///
+
+## Tại sao lại Huỷ kích hoạt một Môi trường ảo
+
+Ví dụ, bạn có thể làm việc trên một dự án `philosophers-stone`, **kích hoạt môi trường ảo**, cài đặt các gói và làm việc với môi trường ảo đó.
+
+Sau đó, bạn muốn làm việc trên **dự án khác** `prisoner-of-azkaban`.
+
+Bạn đi đến dự án đó:
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+```
+
+
+
+Nếu bạn không tắt môi trường ảo cho `philosophers-stone`, khi bạn chạy `python` trong terminal, nó sẽ cố gắng sử dụng Python từ `philosophers-stone`.
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+
+$ python main.py
+
+// Lỗi khi import sirius, nó không được cài đặt 😱
+Traceback (most recent call last):
+ File "main.py", line 1, in
+ import sirius
+```
+
+
+
+Nếu bạn huỷ kích hoạt môi trường ảo hiện tại và kích hoạt môi trường ảo mới cho `prisoner-of-azkaban`, khi bạn chạy `python`, nó sẽ sử dụng Python từ môi trường ảo trong `prisoner-of-azkaban`.
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+
+// Bạn không cần phải ở trong thư mục trước để huỷ kích hoạt, bạn có thể làm điều đó ở bất kỳ đâu, ngay cả sau khi đi đến dự án khác 😎
+$ deactivate
+
+// Kích hoạt môi trường ảo trong prisoner-of-azkaban/.venv 🚀
+$ source .venv/bin/activate
+
+// Bây giờ khi bạn chạy python, nó sẽ tìm thấy gói sirius được cài đặt trong môi trường ảo này ✨
+$ python main.py
+
+I solemnly swear 🐺
+
+(Tôi long trọng thề 🐺 - câu này được lấy từ Harry Potter, chú thích của người dịch)
+```
+
+
+
+## Các cách làm tương tự
+
+Đây là một hướng dẫn đơn giản để bạn có thể bắt đầu và hiểu cách mọi thứ hoạt động **bên trong**.
+
+Có nhiều **cách khác nhau** để quản lí các môi trường ảo, các gói phụ thuộc (requirements), và các dự án.
+
+Một khi bạn đã sẵn sàng và muốn sử dụng một công cụ để **quản lí cả dự án**, các gói phụ thuộc, các môi trường ảo, v.v. Tôi sẽ khuyên bạn nên thử
uv.
+
+`uv` có thể làm nhiều thứ, chẳng hạn:
+
+* **Cài đặt Python** cho bạn, bao gồm nhiều phiên bản khác nhau
+* Quản lí **các môi trường ảo** cho các dự án của bạn
+* Cài đặt **các gói (packages)**
+* Quản lí **các thành phần phụ thuộc và phiên bản** của các gói cho dự án của bạn
+* Đảm bảo rằng bạn có một **tập hợp chính xác** các gói và phiên bản để cài đặt, bao gồm các thành phần phụ thuộc của chúng, để bạn có thể đảm bảo rằng bạn có thể chạy dự án của bạn trong sản xuất chính xác như trong máy tính của bạn trong khi phát triển, điều này được gọi là **locking**
+* Và còn nhiều thứ khác nữa
+
+## Kết luận
+
+Nếu bạn đã đọc và hiểu hết những điều này, khá chắc là bây giờ bạn đã **biết nhiều hơn** về môi trường ảo so với kha khá lập trình viên khác đấy. 🤓
+
+Những hiểu biết chi tiết này có thể sẽ hữu ích với bạn trong tương lai khi mà bạn cần gỡ lỗi một vài thứ phức tạp, và bạn đã có những hiểu biết về **ngọn ngành gốc rễ cách nó hoạt động**. 😎
diff --git a/docs/vi/mkdocs.yml b/docs/vi/mkdocs.yml
new file mode 100644
index 000000000..de18856f4
--- /dev/null
+++ b/docs/vi/mkdocs.yml
@@ -0,0 +1 @@
+INHERIT: ../en/mkdocs.yml
diff --git a/docs/yo/docs/index.md b/docs/yo/docs/index.md
new file mode 100644
index 000000000..d6aa78b3d
--- /dev/null
+++ b/docs/yo/docs/index.md
@@ -0,0 +1,474 @@
+# FastAPI
+
+
+
+
+
+
+
+ Ìlànà wẹ́ẹ́bù FastAPI, iṣẹ́ gíga, ó rọrùn láti kọ̀, o yára láti kóòdù, ó sì ṣetán fún iṣelọpọ ní lílo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+**Àkọsílẹ̀**:
https://fastapi.tiangolo.com
+
+**Orisun Kóòdù**:
https://github.com/fastapi/fastapi
+
+---
+
+FastAPI jẹ́ ìgbàlódé, tí ó yára (iṣẹ-giga), ìlànà wẹ́ẹ́bù fún kikọ àwọn API pẹ̀lú Python èyí tí ó da lori àwọn ìtọ́kasí àmì irúfẹ́ Python.
+
+Àwọn ẹya pàtàkì ni:
+
+* **Ó yára**: Iṣẹ tí ó ga púpọ̀, tí ó wa ni ibamu pẹ̀lú **NodeJS** àti **Go** (ọpẹ si Starlette àti Pydantic). [Ọkan nínú àwọn ìlànà Python ti o yára jùlọ ti o wa](#isesi).
+* **Ó yára láti kóòdù**: O mu iyara pọ si láti kọ àwọn ẹya tuntun kóòdù nipasẹ "Igba ìdá ọgọ́rùn-ún" (i.e. 200%) si "ọ̀ọ́dúrún ìdá ọgọ́rùn-ún" (i.e. 300%).
+* **Àìtọ́ kékeré**: O n din aṣiṣe ku bi ọgbon ìdá ọgọ́rùn-ún (i.e. 40%) ti eda eniyan (oṣiṣẹ kóòdù) fa. *
+* **Ọgbọ́n àti ìmọ̀**: Atilẹyin olootu nla.
Ìparí nibi gbogbo. Àkókò díẹ̀ nipa wíwá ibi tí ìṣòro kóòdù wà.
+* **Irọrun**: A kọ kí ó le rọrun láti lo àti láti kọ ẹkọ nínú rè. Ó máa fún ọ ní àkókò díẹ̀ látı ka àkọsílẹ.
+* **Ó kúkurú ní kikọ**: Ó dín àtúnkọ àti àtúntò kóòdù kù. Ìkéde àṣàyàn kọ̀ọ̀kan nínú rẹ̀ ní ọ̀pọ̀lọpọ̀ àwọn ìlò. O ṣe iranlọwọ láti má ṣe ní ọ̀pọ̀lọpọ̀ àṣìṣe.
+* **Ó lágbára**: Ó ń ṣe àgbéjáde kóòdù tí ó ṣetán fún ìṣelọ́pọ̀. Pẹ̀lú àkọsílẹ̀ tí ó máa ṣàlàyé ara rẹ̀ fún ẹ ní ìbáṣepọ̀ aládàáṣiṣẹ́ pẹ̀lú rè.
+* **Ajohunše/Ìtọ́kasí**: Ó da lori (àti ibamu ni kikun pẹ̀lú) àwọn ìmọ ajohunše/ìtọ́kasí fún àwọn API:
OpenAPI (èyí tí a mọ tẹlẹ si Swagger) àti
JSON Schema.
+
+
* iṣiro yi da lori àwọn idanwo tí ẹgbẹ ìdàgbàsókè FastAPI ṣe, nígbàtí wọn kọ àwọn ohun elo iṣelọpọ kóòdù pẹ̀lú rẹ.
+
+## Àwọn onígbọ̀wọ́
+
+
+
+{% if sponsors %}
+{% for sponsor in sponsors.gold -%}
+

+{% endfor -%}
+{%- for sponsor in sponsors.silver -%}
+

+{% endfor %}
+{% endif %}
+
+
+
+
Àwọn onígbọ̀wọ́ míràn
+
+## Àwọn ero àti èsì
+
+"_[...] Mò ń lo **FastAPI** púpọ̀ ní lẹ́nu àìpẹ́ yìí. [...] Mo n gbero láti lo o pẹ̀lú àwọn ẹgbẹ mi fún gbogbo iṣẹ **ML wa ni Microsoft**. Diẹ nínú wọn ni afikun ti ifilelẹ àwọn ẹya ara ti ọja **Windows** wa pẹ̀lú àwọn ti **Office**._"
+
+
Kabir Khan -
Microsoft (ref)
+
+---
+
+"_A gba àwọn ohun èlò ìwé afọwọkọ **FastAPI** tí kò yí padà láti ṣẹ̀dá olùpín **REST** tí a lè béèrè lọ́wọ́ rẹ̀ láti gba **àsọtẹ́lẹ̀**. [fún Ludwig]_"
+
+
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala -
Uber (ref)
+
+---
+
+"_**Netflix** ni inudidun láti kede itusilẹ orisun kóòdù ti ìlànà iṣọkan **iṣakoso Ìṣòro** wa: **Ìfiránṣẹ́**! [a kọ pẹ̀lú **FastAPI**]_"
+
+
Kevin Glisson, Marc Vilanova, Forest Monsen -
Netflix (ref)
+
+---
+
+"_Inú mi dùn púpọ̀ nípa **FastAPI**. Ó mú inú ẹnì dùn púpọ̀!_"
+
+
+
+---
+
+"_Ní tòótọ́, ohun tí o kọ dára ó sì tún dán. Ní ọ̀pọ̀lọpọ̀ ọ̀nà, ohun tí mo fẹ́ kí **Hug** jẹ́ nìyẹn - ó wúni lórí gan-an láti rí ẹnìkan tí ó kọ́ nǹkan bí èyí._"
+
+
+
+---
+
+"_Ti o ba n wa láti kọ ọkan **ìlànà igbalode** fún kikọ àwọn REST API, ṣayẹwo **FastAPI** [...] Ó yára, ó rọrùn láti lò, ó sì rọrùn láti kọ́[...]_"
+
+"_A ti yipada si **FastAPI** fún **APIs** wa [...] Mo lérò pé wà á fẹ́ràn rẹ̀ [...]_"
+
+
+
+---
+
+"_Ti ẹnikẹni ba n wa láti kọ iṣelọpọ API pẹ̀lú Python, èmi yóò ṣe'dúró fún **FastAPI**. Ó jẹ́ ohun tí **àgbékalẹ̀ rẹ̀ lẹ́wà**, **ó rọrùn láti lò** àti wipe ó ni **ìwọ̀n gíga**, o tí dí **bọtini paati** nínú alakọkọ API ìdàgbàsókè kikọ fún wa, àti pe o ni ipa lori adaṣiṣẹ àti àwọn iṣẹ gẹ́gẹ́ bíi Onímọ̀-ẹ̀rọ TAC tí órí Íńtánẹ́ẹ̀tì_"
+
+
Deon Pillsbury -
Cisco (ref)
+
+---
+
+## **Typer**, FastAPI ti CLIs
+
+

+
+Ti o ba n kọ ohun èlò
CLI láti ṣeé lọ nínú ohun èlò lori ebute kọmputa dipo API, ṣayẹwo
**Typer**.
+
+**Typer** jẹ́ àbúrò ìyá FastAPI kékeré. Àti pé wọ́n kọ́ láti jẹ́ **FastAPI ti CLIs**. ⌨️ 🚀
+
+## Èròjà
+
+FastAPI dúró lórí àwọn èjìká tí àwọn òmíràn:
+
+*
Starlette fún àwọn ẹ̀yà ayélujára.
+*
Pydantic fún àwọn ẹ̀yà àkójọf'áyẹ̀wò.
+
+## Fifi sórí ẹrọ
+
+
+
+```console
+$ pip install fastapi
+
+---> 100%
+```
+
+
+Iwọ yóò tún nílò olupin ASGI, fún iṣelọpọ bii
Uvicorn tabi
Hypercorn.
+
+
+
+```console
+$ pip install "uvicorn[standard]"
+
+---> 100%
+```
+
+
+
+## Àpẹẹrẹ
+
+### Ṣẹ̀dá rẹ̀
+
+* Ṣẹ̀dá fáìlì `main.py (èyí tíí ṣe, akọkọ.py)` pẹ̀lú:
+
+```Python
+from typing import Union
+
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+def read_root():
+ return {"Hello": "World"}
+
+
+@app.get("/items/{item_id}")
+def read_item(item_id: int, q: Union[str, None] = None):
+ return {"item_id": item_id, "q": q}
+```
+
+
+Tàbí lò async def
...
+
+Tí kóòdù rẹ̀ bá ń lò `async` / `await`, lò `async def`:
+
+```Python hl_lines="9 14"
+from typing import Union
+
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+async def read_root():
+ return {"Hello": "World"}
+
+
+@app.get("/items/{item_id}")
+async def read_item(item_id: int, q: Union[str, None] = None):
+ return {"item_id": item_id, "q": q}
+```
+
+**Akiyesi**:
+
+Tí o kò bá mọ̀, ṣàyẹ̀wò ibi tí a ti ní _"In a hurry?"_ (i.e. _"Ní kíákíá?"_) nípa `async` and `await` nínú àkọsílẹ̀.
+
+
+
+### Mu ṣiṣẹ
+
+Mú olupin ṣiṣẹ pẹ̀lú:
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [28720]
+INFO: Started server process [28722]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+
+Nipa aṣẹ kóòdù náà uvicorn main:app --reload
...
+
+Àṣẹ `uvicorn main:app` ń tọ́ka sí:
+
+* `main`: fáìlì náà 'main.py' (Python "module").
+* `app` jẹ object( i.e. nǹkan) tí a ṣẹ̀dá nínú `main.py` pẹ̀lú ilà `app = FastAPI()`.
+* `--reload`: èyí yóò jẹ́ ki olupin tún bẹ̀rẹ̀ lẹ́hìn àwọn àyípadà kóòdù. Jọ̀wọ́, ṣe èyí fún ìdàgbàsókè kóòdù nìkan, má ṣe é ṣe lori àgbéjáde kóòdù tabi fún iṣelọpọ kóòdù.
+
+
+
+
+### Ṣayẹwo rẹ
+
+Ṣii aṣàwákiri kọ̀ǹpútà rẹ ni
http://127.0.0.1:8000/items/5?q=somequery.
+
+Ìwọ yóò sì rí ìdáhùn JSON bíi:
+
+```JSON
+{"item_id": 5, "q": "somequery"}
+```
+
+O tí ṣẹ̀dá API èyí tí yóò:
+
+* Gbà àwọn ìbéèrè HTTP ni àwọn _ipa ọ̀nà_ `/` àti `/items/{item_id}`.
+* Èyí tí àwọn _ipa ọ̀nà_ (i.e. _paths_) méjèèjì gbà àwọn
iṣẹ `GET` (a tun mọ si _àwọn ọna_ HTTP).
+* Èyí tí _ipa ọ̀nà_ (i.e. _paths_) `/items/{item_id}` ní _àwọn ohun-ini ipa ọ̀nà_ tí ó yẹ kí ó jẹ́ `int` i.e. `ÒǸKÀ`.
+* Èyí tí _ipa ọ̀nà_ (i.e. _paths_) `/items/{item_id}` ní àṣàyàn `str` _àwọn ohun-ini_ (i.e. _query parameter_) `q`.
+
+### Ìbáṣepọ̀ àkọsílẹ̀ API
+
+Ní báyìí, lọ sí
http://127.0.0.1:8000/docs.
+
+Lẹ́yìn náà, iwọ yóò rí ìdáhùn àkọsílẹ̀ API tí ó jẹ́ ìbáṣepọ̀ alaifọwọyi/aládàáṣiṣẹ́ (tí a pèṣè nípaṣẹ̀
Swagger UI):
+
+
+
+### Ìdàkejì àkọsílẹ̀ API
+
+Ní báyìí, lọ sí
http://127.0.0.1:8000/redoc.
+
+Wà á rí àwọn àkọsílẹ̀ aládàáṣiṣẹ́ mìíràn (tí a pese nipasẹ
ReDoc):
+
+
+
+## Àpẹẹrẹ ìgbésókè mìíràn
+
+Ní báyìí ṣe àtúnṣe fáìlì `main.py` láti gba kókó èsì láti inú ìbéèrè `PUT`.
+
+Ní báyìí, ṣe ìkéde kókó èsì API nínú kóòdù rẹ nipa lílo àwọn ìtọ́kasí àmì irúfẹ́ Python, ọpẹ́ pàtàkìsi sí Pydantic.
+
+```Python hl_lines="4 9-12 25-27"
+from typing import Union
+
+from fastapi import FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ price: float
+ is_offer: Union[bool, None] = None
+
+
+@app.get("/")
+def read_root():
+ return {"Hello": "World"}
+
+
+@app.get("/items/{item_id}")
+def read_item(item_id: int, q: Union[str, None] = None):
+ return {"item_id": item_id, "q": q}
+
+
+@app.put("/items/{item_id}")
+def update_item(item_id: int, item: Item):
+ return {"item_name": item.name, "item_id": item_id}
+```
+
+Olupin yóò tún ṣe àtúnṣe laifọwọyi/aládàáṣiṣẹ́ (nítorí wípé ó se àfikún `-reload` si àṣẹ kóòdù `uvicorn` lókè).
+
+### Ìbáṣepọ̀ ìgbésókè àkọsílẹ̀ API
+
+Ní báyìí, lọ sí
http://127.0.0.1:8000/docs.
+
+* Ìbáṣepọ̀ àkọsílẹ̀ API yóò ṣe imudojuiwọn àkọsílẹ̀ API laifọwọyi, pẹ̀lú kókó èsì ìdáhùn API tuntun:
+
+
+
+* Tẹ bọtini "Gbiyanju rẹ" i.e. "Try it out", yóò gbà ọ́ láàyè láti jẹ́ kí ó tẹ́ àlàyé tí ó nílò kí ó le sọ̀rọ̀ tààrà pẹ̀lú API:
+
+
+
+* Lẹhinna tẹ bọtini "Ṣiṣe" i.e. "Execute", olùmúlò (i.e. user interface) yóò sọrọ pẹ̀lú API rẹ, yóò ṣe afiranṣẹ àwọn èròjà, pàápàá jùlọ yóò gba àwọn àbájáde yóò si ṣafihan wọn loju ìbòjú:
+
+
+
+### Ìdàkejì ìgbésókè àkọsílẹ̀ API
+
+Ní báyìí, lọ sí
http://127.0.0.1:8000/redoc.
+
+* Ìdàkejì àkọsílẹ̀ API yóò ṣ'afihan ìbéèrè èròjà/pàrámítà tuntun àti kókó èsì ti API:
+
+
+
+### Àtúnyẹ̀wò
+
+Ni akopọ, ìwọ yóò kéde ni **kete** àwọn iru èròjà/pàrámítà, kókó èsì API, abbl (i.e. àti bẹbẹ lọ), bi àwọn èròjà iṣẹ.
+
+O ṣe ìyẹn pẹ̀lú irúfẹ́ àmì ìtọ́kasí ìgbàlódé Python.
+
+O ò nílò láti kọ́ síńtáàsì tuntun, ìlànà tàbí ọ̀wọ́ kíláàsì kan pàtó, abbl (i.e. àti bẹbẹ lọ).
+
+Ìtọ́kasí **Python**
+
+Fún àpẹẹrẹ, fún `int`:
+
+```Python
+item_id: int
+```
+
+tàbí fún àwòṣe `Item` tí ó nira díẹ̀ síi:
+
+```Python
+item: Item
+```
+
+... àti pẹ̀lú ìkéde kan ṣoṣo yẹn ìwọ yóò gbà:
+
+* Atilẹyin olootu, pẹ̀lú:
+ * Pipari.
+ * Àyẹ̀wò irúfẹ́ àmì ìtọ́kasí.
+* Ìfọwọ́sí àkójọf'áyẹ̀wò (i.e. data):
+ * Aṣiṣe alaifọwọyi/aládàáṣiṣẹ́ àti aṣiṣe ti ó hàn kedere nígbàtí àwọn àkójọf'áyẹ̀wò (i.e. data) kò wulo tabi tí kò fẹsẹ̀ múlẹ̀.
+ * Ìfọwọ́sí fún ohun elo JSON tí ó jìn gan-an.
+*
Ìyípadà tí input àkójọf'áyẹ̀wò: tí ó wà láti nẹtiwọọki si àkójọf'áyẹ̀wò àti irúfẹ́ àmì ìtọ́kasí Python. Ó ń ka láti:
+ * JSON.
+ * èròjà ọ̀nà tí ò gbé gbà.
+ * èròjà ìbéèrè.
+ * Àwọn Kúkì
+ * Àwọn Àkọlé
+ * Àwọn Fọọmu
+ * Àwọn Fáìlì
+*
Ìyípadà èsì àkójọf'áyẹ̀wò: yíyípadà láti àkójọf'áyẹ̀wò àti irúfẹ́ àmì ìtọ́kasí Python si nẹtiwọọki (gẹ́gẹ́ bí JSON):
+ * Yí irúfẹ́ àmì ìtọ́kasí padà (`str`, `int`, `float`, `bool`, `list`, abbl i.e. àti bèbè ló).
+ * Àwọn ohun èlò `datetime`.
+ * Àwọn ohun èlò `UUID`.
+ * Àwọn awoṣẹ́ ibi ìpamọ́ àkójọf'áyẹ̀wò.
+ * ...àti ọ̀pọ̀lọpọ̀ díẹ̀ síi.
+* Ìbáṣepọ̀ àkọsílẹ̀ API aládàáṣiṣẹ́, pẹ̀lú ìdàkejì àgbékalẹ̀-àwọn-olùmúlò (i.e user interfaces) méjì:
+ * Àgbékalẹ̀-olùmúlò Swagger.
+ * ReDoc.
+
+---
+
+Nisinsin yi, tí ó padà sí àpẹẹrẹ ti tẹ́lẹ̀, **FastAPI** yóò:
+
+* Fọwọ́ sí i pé `item_id` wà nínú ọ̀nà ìbéèrè HTTP fún `GET` àti `PUT`.
+* Fọwọ́ sí i pé `item_id` jẹ́ irúfẹ́ àmì ìtọ́kasí `int` fún ìbéèrè HTTP `GET` àti `PUT`.
+ * Tí kìí bá ṣe bẹ, oníbàárà yóò ríi àṣìṣe tí ó wúlò, kedere.
+* Ṣàyẹ̀wò bóyá ìbéèrè àṣàyàn pàrámítà kan wà tí orúkọ rẹ̀ ń jẹ́ `q` (gẹ́gẹ́ bíi `http://127.0.0.1:8000/items/foo?q=somequery`) fún ìbéèrè HTTP `GET`.
+ * Bí wọ́n ṣe kéde pàrámítà `q` pẹ̀lú `= None`, ó jẹ́ àṣàyàn (i.e optional).
+ * Láìsí `None` yóò nílò (gẹ́gẹ́ bí kókó èsì ìbéèrè HTTP ṣe wà pẹ̀lú `PUT`).
+* Fún àwọn ìbéèrè HTTP `PUT` sí `/items/{item_id}`, kà kókó èsì ìbéèrè HTTP gẹ́gẹ́ bí JSON:
+ * Ṣàyẹ̀wò pé ó ní àbùdá tí ó nílò èyí tíí ṣe `name` i.e. `orúkọ` tí ó yẹ kí ó jẹ́ `str`.
+ * Ṣàyẹ̀wò pé ó ní àbùdá tí ó nílò èyí tíí ṣe `price` i.e. `iye` tí ó gbọ́dọ̀ jẹ́ `float`.
+ * Ṣàyẹ̀wò pé ó ní àbùdá àṣàyàn `is_offer`, tí ó yẹ kí ó jẹ́ `bool`, tí ó bá wà níbẹ̀.
+ * Gbogbo èyí yóò tún ṣiṣẹ́ fún àwọn ohun èlò JSON tí ó jìn gidi gan-an.
+* Yìí padà láti àti sí JSON lai fi ọwọ́ yi.
+* Ṣe àkọsílẹ̀ ohun gbogbo pẹ̀lú OpenAPI, èyí tí yóò wà ní lílo nípaṣẹ̀:
+ * Àwọn ètò àkọsílẹ̀ ìbáṣepọ̀.
+ * Aládàáṣiṣẹ́ oníbárà èlètò tíí ṣẹ̀dá kóòdù, fún ọ̀pọ̀lọpọ̀ àwọn èdè.
+* Pese àkọsílẹ̀ òní ìbáṣepọ̀ ti àwọn àgbékalẹ̀ ayélujára méjì tààrà.
+
+---
+
+A ń ṣẹ̀ṣẹ̀ ń mú ẹyẹ bọ́ làpò ní, ṣùgbọ́n ó ti ni òye bí gbogbo rẹ̀ ṣe ń ṣiṣẹ́.
+
+Gbiyanju láti yí ìlà padà pẹ̀lú:
+
+```Python
+ return {"item_name": item.name, "item_id": item_id}
+```
+
+...láti:
+
+```Python
+ ... "item_name": item.name ...
+```
+
+...ṣí:
+
+```Python
+ ... "item_price": item.price ...
+```
+
+.. kí o sì wo bí olóòtú rẹ yóò ṣe parí àwọn àbùdá náà fúnra rẹ̀, yóò sì mọ irúfẹ́ wọn:
+
+
+
+Fún àpẹẹrẹ pípé síi pẹ̀lú àwọn àbùdá mìíràn, wo
Ìdánilẹ́kọ̀ọ́ - Ìtọ́sọ́nà Olùmúlò.
+
+**Itaniji gẹ́gẹ́ bí isọ'ye**: ìdánilẹ́kọ̀ọ́ - itọsọna olùmúlò pẹ̀lú:
+
+* Ìkéde àṣàyàn **pàrámítà** láti àwọn oriṣiriṣi ibòmíràn gẹ́gẹ́ bíi: àwọn **àkọlé èsì API**, **kúkì**, **ààyè fọọmu**, àti **fáìlì**.
+* Bíi ó ṣe lé ṣètò **àwọn ìdíwọ́ ìfọwọ́sí** bí `maximum_length` tàbí `regex`.
+* Ó lágbára púpọ̀ ó sì rọrùn láti lo ètò **
Àfikún Ìgbẹ́kẹ̀lé Kóòdù**.
+* Ààbò àti ìfọwọ́sowọ́pọ̀, pẹ̀lú àtìlẹ́yìn fún **OAuth2** pẹ̀lú **àmì JWT** àti **HTTP Ipilẹ ìfọwọ́sowọ́pọ̀**.
+* Àwọn ìlànà ìlọsíwájú (ṣùgbọ́n tí ó rọrùn bákan náà) fún ìkéde **àwọn àwòṣe JSON tó jinlẹ̀** (ọpẹ́ pàtàkìsi sí Pydantic).
+* Iṣọpọ **GraphQL** pẹ̀lú
Strawberry àti àwọn ohun èlò ìwé kóòdù afọwọkọ mìíràn tí kò yí padà.
+* Ọpọlọpọ àwọn àfikún àwọn ẹ̀yà (ọpẹ́ pàtàkìsi sí Starlette) bí:
+ * **WebSockets**
+ * àwọn ìdánwò tí ó rọrùn púpọ̀ lórí HTTPX àti `pytest`
+ * **CORS**
+ * **Cookie Sessions**
+ * ...àti síwájú síi.
+
+## Ìṣesí
+
+Àwọn àlá TechEmpower fi hàn pé **FastAPI** ń ṣiṣẹ́ lábẹ́ Uvicorn gẹ́gẹ́ bí
ọ̀kan lára àwọn ìlànà Python tí ó yára jùlọ tí ó wà, ní ìsàlẹ̀ Starlette àti Uvicorn fúnra wọn (tí FastAPI ń lò fúnra rẹ̀). (*)
+
+Láti ní òye síi nípa rẹ̀, wo abala àwọn
Àlá.
+
+## Àṣàyàn Àwọn Àfikún Ìgbẹ́kẹ̀lé Kóòdù
+
+Èyí tí Pydantic ń lò:
+
+*
email-validator
- fún ifọwọsi ímeèlì.
+*
pydantic-settings
- fún ètò ìsàkóso.
+*
pydantic-extra-types
- fún àfikún oríṣi láti lọ pẹ̀lú Pydantic.
+
+Èyí tí Starlette ń lò:
+
+*
httpx
- Nílò tí ó bá fẹ́ láti lọ `TestClient`.
+*
jinja2
- Nílò tí ó bá fẹ́ láti lọ iṣeto awoṣe aiyipada.
+*
python-multipart
- Nílò tí ó bá fẹ́ láti ṣe àtìlẹ́yìn fún
"àyẹ̀wò" fọọmu, pẹ̀lú `request.form()`.
+*
itsdangerous
- Nílò fún àtìlẹ́yìn `SessionMiddleware`.
+*
pyyaml
- Nílò fún àtìlẹ́yìn Starlette's `SchemaGenerator` (ó ṣe ṣe kí ó má nílò rẹ̀ fún FastAPI).
+
+Èyí tí FastAPI / Starlette ń lò:
+
+*
uvicorn
- Fún olupin tí yóò sẹ́ àmúyẹ àti tí yóò ṣe ìpèsè fún iṣẹ́ rẹ tàbí ohun èlò rẹ.
+*
orjson
- Nílò tí ó bá fẹ́ láti lọ `ORJSONResponse`.
+*
ujson
- Nílò tí ó bá fẹ́ láti lọ `UJSONResponse`.
+
+Ó lè fi gbogbo àwọn wọ̀nyí sórí ẹrọ pẹ̀lú `pip install "fastapi[all]"`.
+
+## Iwe-aṣẹ
+
+Iṣẹ́ yìí ni iwe-aṣẹ lábẹ́ àwọn òfin tí iwe-aṣẹ MIT.
diff --git a/docs/yo/mkdocs.yml b/docs/yo/mkdocs.yml
new file mode 100644
index 000000000..de18856f4
--- /dev/null
+++ b/docs/yo/mkdocs.yml
@@ -0,0 +1 @@
+INHERIT: ../en/mkdocs.yml
diff --git a/docs/zh-hant/docs/about/index.md b/docs/zh-hant/docs/about/index.md
new file mode 100644
index 000000000..5dcee68f2
--- /dev/null
+++ b/docs/zh-hant/docs/about/index.md
@@ -0,0 +1,3 @@
+# 關於 FastAPI
+
+關於 FastAPI、其設計、靈感來源等更多資訊。 🤓
diff --git a/docs/zh-hant/docs/async.md b/docs/zh-hant/docs/async.md
new file mode 100644
index 000000000..6ab75d2ab
--- /dev/null
+++ b/docs/zh-hant/docs/async.md
@@ -0,0 +1,442 @@
+# 並行與 async / await
+
+有關*路徑操作函式*的 `async def` 語法的細節與非同步 (asynchronous) 程式碼、並行 (concurrency) 與平行 (parallelism) 的一些背景知識。
+
+## 趕時間嗎?
+
+
TL;DR:
+
+如果你正在使用要求你以 `await` 語法呼叫的第三方函式庫,例如:
+
+```Python
+results = await some_library()
+```
+
+然後,使用 `async def` 宣告你的*路徑操作函式*:
+
+
+```Python hl_lines="2"
+@app.get('/')
+async def read_results():
+ results = await some_library()
+ return results
+```
+
+/// note | 注意
+
+你只能在 `async def` 建立的函式內使用 `await`。
+
+///
+
+---
+
+如果你使用的是第三方函式庫並且它需要與某些外部資源(例如資料庫、API、檔案系統等)進行通訊,但不支援 `await`(目前大多數資料庫函式庫都是這樣),在這種情況下,你可以像平常一樣使用 `def` 宣告*路徑操作函式*,如下所示:
+
+```Python hl_lines="2"
+@app.get('/')
+def results():
+ results = some_library()
+ return results
+```
+
+---
+
+如果你的應用程式不需要與外部資源進行任何通訊並等待其回應,請使用 `async def`。
+
+---
+
+如果你不確定該用哪個,直接用 `def` 就好。
+
+---
+
+**注意**:你可以在*路徑操作函式*中混合使用 `def` 和 `async def` ,並使用最適合你需求的方式來定義每個函式。FastAPI 會幫你做正確的處理。
+
+無論如何,在上述哪種情況下,FastAPI 仍將以非同步方式運行,並且速度非常快。
+
+但透過遵循上述步驟,它將能進行一些效能最佳化。
+
+## 技術細節
+
+現代版本的 Python 支援使用 **「協程」** 的 **`async` 和 `await`** 語法來寫 **「非同步程式碼」**。
+
+接下來我們逐一介紹:
+
+* **非同步程式碼**
+* **`async` 和 `await`**
+* **協程**
+
+## 非同步程式碼
+
+非同步程式碼僅意味著程式語言 💬 有辦法告訴電腦/程式 🤖 在程式碼中的某個點,它 🤖 需要等待某些事情完成。讓我們假設這些事情被稱為「慢速檔案」📝。
+
+因此,在等待「慢速檔案」📝 完成的這段時間,電腦可以去處理一些其他工作。
+
+接著程式 🤖 會在有空檔時回來查看是否有等待的工作已經完成,並執行必要的後續操作。
+
+接下來,它 🤖 完成第一個工作(例如我們的「慢速檔案」📝)並繼續執行相關的所有操作。
+這個「等待其他事情」通常指的是一些相對較慢的(與處理器和 RAM 記憶體的速度相比)的
I/O 操作,比如說:
+
+* 透過網路傳送來自用戶端的資料
+* 從網路接收來自用戶端的資料
+* 從磁碟讀取檔案內容
+* 將內容寫入磁碟
+* 遠端 API 操作
+* 資料庫操作
+* 資料庫查詢
+* 等等
+
+由於大部分的執行時間都消耗在等待
I/O 操作上,因此這些操作被稱為 "I/O 密集型" 操作。
+
+之所以稱為「非同步」,是因為電腦/程式不需要與那些耗時的任務「同步」,等待任務完成的精確時間,然後才能取得結果並繼續工作。
+
+相反地,非同步系統在任務完成後,可以讓任務稍微等一下(幾微秒),等待電腦/程式完成手頭上的其他工作,然後再回來取得結果繼續進行。
+
+相對於「非同步」(asynchronous),「同步」(synchronous)也常被稱作「順序性」(sequential),因為電腦/程式會依序執行所有步驟,即便這些步驟涉及等待,才會切換到其他任務。
+
+### 並行與漢堡
+
+上述非同步程式碼的概念有時也被稱為「並行」,它不同於「平行」。
+
+並行和平行都與 "不同的事情或多或少同時發生" 有關。
+
+但並行和平行之間的細節是完全不同的。
+
+為了理解差異,請想像以下有關漢堡的故事:
+
+### 並行漢堡
+
+你和你的戀人去速食店,排隊等候時,收銀員正在幫排在你前面的人點餐。😍
+
+

+
+輪到你了,你給你與你的戀人點了兩個豪華漢堡。🍔🍔
+
+

+
+收銀員通知廚房準備你的漢堡(儘管他們還在為前面其他顧客準備食物)。
+
+

+
+之後你完成付款。💸
+
+收銀員給你一個號碼牌。
+
+

+
+在等待漢堡的同時,你可以與戀人選一張桌子,然後坐下來聊很長一段時間(因為漢堡十分豪華,準備特別費工。)
+
+這段時間,你還能欣賞你的戀人有多麼的可愛、聰明與迷人。✨😍✨
+
+

+
+當你和戀人邊聊天邊等待時,你會不時地查看櫃檯上的顯示的號碼,確認是否已經輪到你了。
+
+然後在某個時刻,終於輪到你了。你走到櫃檯,拿了漢堡,然後回到桌子上。
+
+

+
+你和戀人享用這頓大餐,整個過程十分開心✨
+
+

+
+/// info
+
+漂亮的插畫來自
Ketrina Thompson. 🎨
+
+///
+
+---
+
+想像你是故事中的電腦或程式 🤖。
+
+當你排隊時,你在放空😴,等待輪到你,沒有做任何「生產性」的事情。但這沒關係,因為收銀員只是接單(而不是準備食物),所以排隊速度很快。
+
+然後,當輪到你時,你開始做真正「有生產力」的工作,處理菜單,決定你想要什麼,替戀人選擇餐點,付款,確認你給了正確的帳單或信用卡,檢查你是否被正確收費,確認訂單中的項目是否正確等等。
+
+但是,即使你還沒有拿到漢堡,你與收銀員的工作已經「暫停」了 ⏸,因為你必須等待 🕙 漢堡準備好。
+
+但當你離開櫃檯,坐到桌子旁,拿著屬於你的號碼等待時,你可以把注意力 🔀 轉移到戀人身上,並開始「工作」⏯ 🤓——也就是和戀人調情 😍。這時你又開始做一些非常「有生產力」的事情。
+
+接著,收銀員 💁 將你的號碼顯示在櫃檯螢幕上,並告訴你「漢堡已經做好了」。但你不會瘋狂地立刻跳起來,因為顯示的號碼變成了你的。你知道沒有人會搶走你的漢堡,因為你有自己的號碼,他們也有他們的號碼。
+
+所以你會等戀人講完故事(完成當前的工作 ⏯/正在進行的任務 🤓),然後微笑著溫柔地說你要去拿漢堡了 ⏸。
+
+然後你走向櫃檯 🔀,回到已經完成的最初任務 ⏯,拿起漢堡,說聲謝謝,並帶回桌上。這就結束了與櫃檯的互動步驟/任務 ⏹,接下來會產生一個新的任務,「吃漢堡」 🔀 ⏯,而先前的「拿漢堡」任務已經完成了 ⏹。
+
+### 平行漢堡
+
+現在,讓我們來想像這裡不是「並行漢堡」,而是「平行漢堡」。
+
+你和戀人一起去吃平行的速食餐。
+
+你們站在隊伍中,前面有幾位(假設有 8 位)既是收銀員又是廚師的員工,他們同時接單並準備餐點。
+
+所有排在你前面的人都在等著他們的漢堡準備好後才會離開櫃檯,因為每位收銀員在接完單後,馬上會去準備漢堡,然後才回來處理下一個訂單。
+
+

+
+終於輪到你了,你為你和你的戀人點了兩個非常豪華的漢堡。
+
+你付款了 💸。
+
+

+
+收銀員走進廚房準備食物。
+
+你站在櫃檯前等待 🕙,以免其他人先拿走你的漢堡,因為這裡沒有號碼牌系統。
+
+

+
+由於你和戀人都忙著不讓別人搶走你的漢堡,等漢堡準備好時,你根本無法專心和戀人互動。😞
+
+這是「同步」(synchronous)工作,你和收銀員/廚師 👨🍳 是「同步化」的。你必須等到 🕙 收銀員/廚師 👨🍳 完成漢堡並交給你的那一刻,否則別人可能會拿走你的餐點。
+
+

+
+最終,經過長時間的等待 🕙,收銀員/廚師 👨🍳 拿著漢堡回來了。
+
+

+
+你拿著漢堡,和你的戀人回到餐桌。
+
+你們僅僅是吃完漢堡,然後就結束了。⏹
+
+

+
+整個過程中沒有太多的談情說愛,因為大部分時間 🕙 都花在櫃檯前等待。😞
+
+/// info
+
+漂亮的插畫來自
Ketrina Thompson. 🎨
+
+///
+
+---
+
+在這個平行漢堡的情境下,你是一個程式 🤖 且有兩個處理器(你和戀人),兩者都在等待 🕙 並專注於等待櫃檯上的餐點 🕙,等待的時間非常長。
+
+這家速食店有 8 個處理器(收銀員/廚師)。而並行漢堡店可能只有 2 個處理器(一位收銀員和一位廚師)。
+
+儘管如此,最終的體驗並不是最理想的。😞
+
+---
+
+這是與漢堡類似的故事。🍔
+
+一個更「現實」的例子,想像一間銀行。
+
+直到最近,大多數銀行都有多位出納員 👨💼👨💼👨💼👨💼,以及一條長長的隊伍 🕙🕙🕙🕙🕙🕙🕙🕙。
+
+所有的出納員都在一個接一個地滿足每位客戶的所有需求 👨💼⏯。
+
+你必須長時間排隊 🕙,不然就會失去機會。
+
+所以,你不會想帶你的戀人 😍 一起去銀行辦事 🏦。
+
+### 漢堡結論
+
+在「和戀人一起吃速食漢堡」的這個場景中,由於有大量的等待 🕙,使用並行系統 ⏸🔀⏯ 更有意義。
+
+這也是大多數 Web 應用的情況。
+
+許多用戶正在使用你的應用程式,而你的伺服器則在等待 🕙 這些用戶不那麼穩定的網路來傳送請求。
+
+接著,再次等待 🕙 回應。
+
+這種「等待」 🕙 通常以微秒來衡量,但累加起來,最終還是花費了很多等待時間。
+
+這就是為什麼對於 Web API 來說,使用非同步程式碼 ⏸🔀⏯ 是非常有意義的。
+
+這種類型的非同步性正是 NodeJS 成功的原因(儘管 NodeJS 不是平行的),這也是 Go 語言作為程式語言的一個強大優勢。
+
+這與 **FastAPI** 所能提供的性能水平相同。
+
+你可以同時利用並行性和平行性,進一步提升效能,這比大多數已測試的 NodeJS 框架都更快,並且與 Go 語言相當,而 Go 是一種更接近 C 的編譯語言(
感謝 Starlette)。
+
+### 並行比平行更好嗎?
+
+不是的!這不是故事的本意。
+
+並行與平行不同。並行在某些 **特定** 的需要大量等待的情境下表現更好。正因如此,並行在 Web 應用程式開發中通常比平行更有優勢。但並不是所有情境都如此。
+
+因此,為了平衡報導,想像下面這個短故事
+
+> 你需要打掃一間又大又髒的房子。
+
+*是的,這就是全部的故事。*
+
+---
+
+這裡沒有任何需要等待 🕙 的地方,只需要在房子的多個地方進行大量的工作。
+
+你可以像漢堡的例子那樣輪流進行,先打掃客廳,再打掃廚房,但由於你不需要等待 🕙 任何事情,只需要持續地打掃,輪流並不會影響任何結果。
+
+無論輪流執行與否(並行),你都需要相同的工時完成任務,同時需要執行相同工作量。
+
+但是,在這種情境下,如果你可以邀請8位前收銀員/廚師(現在是清潔工)來幫忙,每個人(加上你)負責房子的某個區域,這樣你就可以 **平行** 地更快完成工作。
+
+在這個場景中,每個清潔工(包括你)都是一個處理器,完成工作的一部分。
+
+由於大多數的執行時間都花在實際的工作上(而不是等待),而電腦中的工作由
CPU 完成,因此這些問題被稱為「CPU 密集型」。
+
+---
+
+常見的 CPU 密集型操作範例包括那些需要進行複雜數學計算的任務。
+
+例如:
+
+* **音訊**或**圖像處理**;
+* **電腦視覺**:一張圖片由數百萬個像素組成,每個像素有 3 個值/顏色,處理這些像素通常需要同時進行大量計算;
+* **機器學習**: 通常需要大量的「矩陣」和「向量」運算。想像一個包含數字的巨大電子表格,並所有的數字同時相乘;
+* **深度學習**: 這是機器學習的子領域,同樣適用。只不過這不僅僅是一張數字表格,而是大量的數據集合,並且在很多情況下,你會使用特殊的處理器來構建或使用這些模型。
+
+### 並行 + 平行: Web + 機器學習
+
+使用 **FastAPI**,你可以利用並行的優勢,這在 Web 開發中非常常見(這也是 NodeJS 的最大吸引力)。
+
+但你也可以利用平行與多行程 (multiprocessing)(讓多個行程同時運行) 的優勢來處理機器學習系統中的 **CPU 密集型**工作。
+
+這一點,再加上 Python 是 **資料科學**、機器學習,尤其是深度學習的主要語言,讓 **FastAPI** 成為資料科學/機器學習 Web API 和應用程式(以及許多其他應用程式)的絕佳選擇。
+
+想了解如何在生產環境中實現這種平行性,請參見 [部屬](deployment/index.md){.internal-link target=_blank}。
+
+## `async` 和 `await`
+
+現代 Python 版本提供一種非常直觀的方式定義非同步程式碼。這使得它看起來就像正常的「順序」程式碼,並在適當的時機「等待」。
+
+當某個操作需要等待才能回傳結果,並且支援這些新的 Python 特性時,你可以像這樣編寫程式碼:
+
+```Python
+burgers = await get_burgers(2)
+```
+
+這裡的關鍵是 `await`。它告訴 Python 必須等待 ⏸ `get_burgers(2)` 完成它的工作 🕙, 然後將結果儲存在 `burgers` 中。如此,Python 就可以在此期間去處理其他事情 🔀 ⏯ (例如接收另一個請求)。
+
+要讓 `await` 運作,它必須位於支持非同步功能的函式內。為此,只需使用 `async def` 宣告函式:
+
+```Python hl_lines="1"
+async def get_burgers(number: int):
+ # Do some asynchronous stuff to create the burgers
+ return burgers
+```
+
+...而不是 `def`:
+
+```Python hl_lines="2"
+# This is not asynchronous
+def get_sequential_burgers(number: int):
+ # Do some sequential stuff to create the burgers
+ return burgers
+```
+
+使用 `async def`,Python Python 知道在該函式內需要注意 `await`,並且它可以「暫停」 ⏸ 執行該函式,然後執行其他任務 🔀 後回來。
+
+當你想要呼叫 `async def` 函式時,必須使用「await」。因此,這樣寫將無法運行:
+
+```Python
+# This won't work, because get_burgers was defined with: async def
+burgers = get_burgers(2)
+```
+
+---
+
+如果你正在使用某個函式庫,它告訴你可以使用 `await` 呼叫它,那麼你需要用 `async def` 定義*路徑操作函式*,如:
+
+```Python hl_lines="2-3"
+@app.get('/burgers')
+async def read_burgers():
+ burgers = await get_burgers(2)
+ return burgers
+```
+
+### 更多技術細節
+
+你可能已經注意到,`await` 只能在 `async def` 定義的函式內使用。
+
+但同時,使用 `async def` 定義的函式本身也必須被「等待」。所以,帶有 `async def` 函式只能在其他使用 `async def` 定義的函式內呼叫。
+
+那麼,這就像「先有雞還是先有蛋」的問題,要如何呼叫第一個 `async` 函式呢?
+
+如果你使用 FastAPI,無需擔心這個問題,因為「第一個」函式將是你的*路徑操作函式*,FastAPI 會知道如何正確處理這個問題。
+
+但如果你想在沒有 FastAPI 的情況下使用 `async` / `await`,你也可以這樣做。
+
+### 編寫自己的非同步程式碼
+
+Starlette (和 **FastAPI**) 是基於
AnyIO 實作的,這使得它們與 Python 標準函式庫相容
asyncio 和
Trio。
+
+特別是,你可以直接使用
AnyIO 來處理更複雜的並行使用案例,這些案例需要你在自己的程式碼中使用更高階的模式。
+
+即使你不使用 **FastAPI**,你也可以使用
AnyIO 來撰寫自己的非同步應用程式,並獲得高相容性及一些好處(例如結構化並行)。
+
+### 其他形式的非同步程式碼
+
+使用 `async` 和 `await` 的風格在語言中相對較新。
+
+但它使處理異步程式碼變得更加容易。
+
+相同的語法(或幾乎相同的語法)最近也被包含在現代 JavaScript(無論是瀏覽器還是 NodeJS)中。
+
+但在此之前,處理異步程式碼要更加複雜和困難。
+
+在較舊的 Python 版本中,你可能會使用多執行緒或
Gevent。但這些程式碼要更難以理解、調試和思考。
+
+在較舊的 NodeJS / 瀏覽器 JavaScript 中,你會使用「回呼」,這可能會導致
回呼地獄。
+
+## 協程
+
+**協程** 只是 `async def` 函式所回傳的非常特殊的事物名稱。Python 知道它是一個類似函式的東西,可以啟動它,並且在某個時刻它會結束,但它也可能在內部暫停 ⏸,只要遇到 `await`。
+
+這種使用 `async` 和 `await` 的非同步程式碼功能通常被概括為「協程」。這與 Go 語言的主要特性「Goroutines」相似。
+
+## 結論
+
+讓我們再次回顧之前的句子:
+
+> 現代版本的 Python 支持使用 **"協程"** 的 **`async` 和 `await`** 語法來寫 **"非同步程式碼"**。
+
+現在應該能明白其含意了。✨
+
+這些就是驅動 FastAPI(通過 Starlette)運作的原理,也讓它擁有如此驚人的效能。
+
+## 非常技術性的細節
+
+/// warning
+
+你大概可以跳過這段。
+
+這裡是有關 FastAPI 內部技術細節。
+
+如果你有相當多的技術背景(例如協程、執行緒、阻塞等),並且對 FastAPI 如何處理 `async def` 與常規 `def` 感到好奇,請繼續閱讀。
+
+///
+
+### 路徑操作函数
+
+當你使用 `def` 而不是 `async def` 宣告*路徑操作函式*時,該函式會在外部的執行緒池(threadpool)中執行,然後等待結果,而不是直接呼叫(因為這樣會阻塞伺服器)。
+
+如果你來自於其他不以這種方式運作的非同步框架,而且你習慣於使用普通的 `def` 定義僅進行簡單計算的*路徑操作函式*,目的是獲得微小的性能增益(大約 100 奈秒),請注意,在 FastAPI 中,效果會完全相反。在這些情況下,最好使用 `async def`除非你的*路徑操作函式*執行阻塞的
I/O 的程式碼。
+
+不過,在這兩種情況下,**FastAPI** [仍然很快](index.md#_11){.internal-link target=_blank}至少與你之前的框架相當(或者更快)。
+
+### 依賴項(Dependencies)
+
+同樣適用於[依賴項](tutorial/dependencies/index.md){.internal-link target=_blank}。如果依賴項是一個標準的 `def` 函式,而不是 `async def`,那麼它在外部的執行緒池被運行。
+
+### 子依賴項
+
+你可以擁有多個相互依賴的依賴項和[子依賴項](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} (作為函式定義的參數),其中一些可能是用 `async def` 宣告,也可能是用 `def` 宣告。它們仍然可以正常運作,用 `def` 定義的那些將會在外部的執行緒中呼叫(來自執行緒池),而不是被「等待」。
+
+### 其他輔助函式
+
+你可以直接呼叫任何使用 `def` 或 `async def` 建立的其他輔助函式,FastAPI 不會影響你呼叫它們的方式。
+
+這與 FastAPI 為你呼叫*路徑操作函式*和依賴項的邏輯有所不同。
+
+如果你的輔助函式是用 `def` 宣告的,它將會被直接呼叫(按照你在程式碼中撰寫的方式),而不是在執行緒池中。如果該函式是用 `async def` 宣告,那麼你在呼叫時應該使用 `await` 等待其結果。
+
+---
+
+再一次強調,這些都是非常技術性的細節,如果你特地在尋找這些資訊,這些內容可能會對你有幫助。
+
+否則,只需遵循上面提到的指引即可:
趕時間嗎?.
diff --git a/docs/zh-hant/docs/benchmarks.md b/docs/zh-hant/docs/benchmarks.md
new file mode 100644
index 000000000..c59e8e71c
--- /dev/null
+++ b/docs/zh-hant/docs/benchmarks.md
@@ -0,0 +1,34 @@
+# 基準測試
+
+由第三方機構 TechEmpower 的基準測試表明在 Uvicorn 下運行的 **FastAPI** 應用程式是
最快的 Python 可用框架之一,僅次於 Starlette 和 Uvicorn 本身(於 FastAPI 內部使用)。
+
+但是在查看基準得分和對比時,請注意以下幾點。
+
+## 基準測試和速度
+
+當你查看基準測試時,時常會見到幾個不同類型的工具被同時進行測試。
+
+具體來說,是將 Uvicorn、Starlette 和 FastAPI 同時進行比較(以及許多其他工具)。
+
+該工具解決的問題越簡單,其效能就越好。而且大多數基準測試不會測試該工具提供的附加功能。
+
+層次結構如下:
+
+* **Uvicorn**:ASGI 伺服器
+ * **Starlette**:(使用 Uvicorn)一個網頁微框架
+ * **FastAPI**:(使用 Starlette)一個 API 微框架,具有用於建立 API 的多個附加功能、資料驗證等。
+
+* **Uvicorn**:
+ * 具有最佳效能,因為除了伺服器本身之外,它沒有太多額外的程式碼。
+ * 你不會直接在 Uvicorn 中編寫應用程式。這意味著你的程式碼必須或多或少地包含 Starlette(或 **FastAPI**)提供的所有程式碼。如果你這樣做,你的最終應用程式將具有與使用框架相同的開銷並最大限度地減少應用程式程式碼和錯誤。
+ * 如果你要比較 Uvicorn,請將其與 Daphne、Hypercorn、uWSGI 等應用程式伺服器進行比較。
+* **Starlette**:
+ * 繼 Uvicorn 之後的次佳表現。事實上,Starlette 使用 Uvicorn 來運行。因此它將可能只透過執行更多程式碼而變得比 Uvicorn「慢」。
+ * 但它為你提供了建立簡單網頁應用程式的工具,以及基於路徑的路由等。
+ * 如果你要比較 Starlette,請將其與 Sanic、Flask、Django 等網頁框架(或微框架)進行比較。
+* **FastAPI**:
+ * 就像 Starlette 使用 Uvicorn 並不能比它更快一樣, **FastAPI** 使用 Starlette,所以它不能比它更快。
+ * FastAPI 在 Starlette 基礎之上提供了更多功能。包含建構 API 時所需要的功能,例如資料驗證和序列化。FastAPI 可以幫助你自動產生 API 文件,(應用程式啟動時將會自動生成文件,所以不會增加應用程式運行時的開銷)。
+ * 如果你沒有使用 FastAPI 而是直接使用 Starlette(或其他工具,如 Sanic、Flask、Responder 等),你將必須自行實現所有資料驗證和序列化。因此,你的最終應用程式仍然具有與使用 FastAPI 建置相同的開銷。在許多情況下,這種資料驗證和序列化是應用程式中編寫最大量的程式碼。
+ * 因此透過使用 FastAPI,你可以節省開發時間、錯誤與程式碼數量,並且相比不使用 FastAPI 你很大可能會獲得相同或更好的效能(因為那樣你必須在程式碼中實現所有相同的功能)。
+ * 如果你要與 FastAPI 比較,請將其與能夠提供資料驗證、序列化和文件的網頁應用程式框架(或工具集)進行比較,例如 Flask-apispec、NestJS、Molten 等框架。
diff --git a/docs/zh-hant/docs/deployment/cloud.md b/docs/zh-hant/docs/deployment/cloud.md
new file mode 100644
index 000000000..29ebe3ff5
--- /dev/null
+++ b/docs/zh-hant/docs/deployment/cloud.md
@@ -0,0 +1,17 @@
+# 在雲端部署 FastAPI
+
+你幾乎可以使用**任何雲端供應商**來部署你的 FastAPI 應用程式。
+
+在大多數情況下,主要的雲端供應商都有部署 FastAPI 的指南。
+
+## 雲端供應商 - 贊助商
+
+一些雲端供應商 ✨ [**贊助 FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨,這確保了 FastAPI 及其**生態系統**持續健康地**發展**。
+
+這也展現了他們對 FastAPI 和其**社群**(包括你)的真正承諾,他們不僅希望為你提供**優質的服務**,還希望確保你擁有一個**良好且健康的框架**:FastAPI。🙇
+
+你可能會想嘗試他們的服務,以下有他們的指南:
+
+*
Platform.sh
+*
Porter
+*
Coherence
diff --git a/docs/zh-hant/docs/deployment/index.md b/docs/zh-hant/docs/deployment/index.md
new file mode 100644
index 000000000..1726562b4
--- /dev/null
+++ b/docs/zh-hant/docs/deployment/index.md
@@ -0,0 +1,21 @@
+# 部署
+
+部署 **FastAPI** 應用程式相對容易。
+
+## 部署是什麼意思
+
+**部署**應用程式指的是執行一系列必要的步驟,使其能夠**讓使用者存取和使用**。
+
+對於一個 **Web API**,部署通常涉及將其放置在**遠端伺服器**上,並使用性能優良且穩定的**伺服器程式**,確保使用者能夠高效、無中斷地存取應用程式,且不會遇到問題。
+
+這與**開發**階段形成鮮明對比,在**開發**階段,你會不斷更改程式碼、破壞程式碼、修復程式碼,然後停止和重新啟動伺服器等。
+
+## 部署策略
+
+根據你的使用場景和使用工具,有多種方法可以實現此目的。
+
+你可以使用一些工具自行**部署伺服器**,你也可以使用能為你完成部分工作的**雲端服務**,或其他可能的選項。
+
+我將向你展示在部署 **FastAPI** 應用程式時你可能應該記住的一些主要概念(儘管其中大部分適用於任何其他類型的 Web 應用程式)。
+
+在接下來的部分中,你將看到更多需要記住的細節以及一些技巧。 ✨
diff --git a/docs/zh-hant/docs/environment-variables.md b/docs/zh-hant/docs/environment-variables.md
new file mode 100644
index 000000000..a1598fc01
--- /dev/null
+++ b/docs/zh-hant/docs/environment-variables.md
@@ -0,0 +1,298 @@
+# 環境變數
+
+/// tip
+
+如果你已經知道什麼是「環境變數」並且知道如何使用它們,你可以放心跳過這一部分。
+
+///
+
+環境變數(也稱為「**env var**」)是一個獨立於 Python 程式碼**之外**的變數,它存在於**作業系統**中,可以被你的 Python 程式碼(或其他程式)讀取。
+
+環境變數對於處理應用程式**設定**(作為 Python **安裝**的一部分等方面)非常有用。
+
+## 建立和使用環境變數
+
+你在 **shell(終端機)**中就可以**建立**和使用環境變數,並不需要用到 Python:
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+// 你可以使用以下指令建立一個名為 MY_NAME 的環境變數
+$ export MY_NAME="Wade Wilson"
+
+// 然後,你可以在其他程式中使用它,例如
+$ echo "Hello $MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+// 建立一個名為 MY_NAME 的環境變數
+$ $Env:MY_NAME = "Wade Wilson"
+
+// 在其他程式中使用它,例如
+$ echo "Hello $Env:MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+## 在 Python 中讀取環境變數
+
+你也可以在 Python **之外**的終端機中建立環境變數(或使用其他方法),然後在 Python 中**讀取**它們。
+
+例如,你可以建立一個名為 `main.py` 的檔案,其中包含以下內容:
+
+```Python hl_lines="3"
+import os
+
+name = os.getenv("MY_NAME", "World")
+print(f"Hello {name} from Python")
+```
+
+/// tip
+
+第二個參數是
`os.getenv()` 的預設回傳值。
+
+如果沒有提供,預設值為 `None`,這裡我們提供 `"World"` 作為預設值。
+
+///
+
+然後你可以呼叫這個 Python 程式:
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+// 這裡我們還沒有設定環境變數
+$ python main.py
+
+// 因為我們沒有設定環境變數,所以我們得到的是預設值
+
+Hello World from Python
+
+// 但是如果我們事先建立過一個環境變數
+$ export MY_NAME="Wade Wilson"
+
+// 然後再次呼叫程式
+$ python main.py
+
+// 現在就可以讀取到環境變數了
+
+Hello Wade Wilson from Python
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+// 這裡我們還沒有設定環境變數
+$ python main.py
+
+// 因為我們沒有設定環境變數,所以我們得到的是預設值
+
+Hello World from Python
+
+// 但是如果我們事先建立過一個環境變數
+$ $Env:MY_NAME = "Wade Wilson"
+
+// 然後再次呼叫程式
+$ python main.py
+
+// 現在就可以讀取到環境變數了
+
+Hello Wade Wilson from Python
+```
+
+
+
+////
+
+由於環境變數可以在程式碼之外設定,但可以被程式碼讀取,並且不必與其他檔案一起儲存(提交到 `git`),因此通常用於配置或**設定**。
+
+你還可以為**特定的程式呼叫**建立特定的環境變數,該環境變數僅對該程式可用,且僅在其執行期間有效。
+
+要實現這一點,只需在同一行內(程式本身之前)建立它:
+
+
+
+```console
+// 在這個程式呼叫的同一行中建立一個名為 MY_NAME 的環境變數
+$ MY_NAME="Wade Wilson" python main.py
+
+// 現在就可以讀取到環境變數了
+
+Hello Wade Wilson from Python
+
+// 在此之後這個環境變數將不再存在
+$ python main.py
+
+Hello World from Python
+```
+
+
+
+/// tip
+
+你可以在
The Twelve-Factor App: 配置中了解更多資訊。
+
+///
+
+## 型別和驗證
+
+這些環境變數只能處理**文字字串**,因為它們是位於 Python 範疇之外的,必須與其他程式和作業系統的其餘部分相容(甚至與不同的作業系統相容,如 Linux、Windows、macOS)。
+
+這意味著從環境變數中讀取的**任何值**在 Python 中都將是一個 `str`,任何型別轉換或驗證都必須在程式碼中完成。
+
+你將在[進階使用者指南 - 設定和環境變數](./advanced/settings.md)中了解更多關於使用環境變數處理**應用程式設定**的資訊。
+
+## `PATH` 環境變數
+
+有一個**特殊的**環境變數稱為 **`PATH`**,作業系統(Linux、macOS、Windows)用它來查找要執行的程式。
+
+`PATH` 變數的值是一個長字串,由 Linux 和 macOS 上的冒號 `:` 分隔的目錄組成,而在 Windows 上則是由分號 `;` 分隔的。
+
+例如,`PATH` 環境變數可能如下所示:
+
+//// tab | Linux, macOS
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
+```
+
+這意味著系統應該在以下目錄中查找程式:
+
+- `/usr/local/bin`
+- `/usr/bin`
+- `/bin`
+- `/usr/sbin`
+- `/sbin`
+
+////
+
+//// tab | Windows
+
+```plaintext
+C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32
+```
+
+這意味著系統應該在以下目錄中查找程式:
+
+- `C:\Program Files\Python312\Scripts`
+- `C:\Program Files\Python312`
+- `C:\Windows\System32`
+
+////
+
+當你在終端機中輸入一個**指令**時,作業系統會在 `PATH` 環境變數中列出的**每個目錄**中**查找**程式。
+
+例如,當你在終端機中輸入 `python` 時,作業系統會在該列表中的**第一個目錄**中查找名為 `python` 的程式。
+
+如果找到了,那麼作業系統將**使用它**;否則,作業系統會繼續在**其他目錄**中查找。
+
+### 安裝 Python 並更新 `PATH`
+
+安裝 Python 時,可能會詢問你是否要更新 `PATH` 環境變數。
+
+//// tab | Linux, macOS
+
+假設你安裝了 Python,並將其安裝在目錄 `/opt/custompython/bin` 中。
+
+如果你選擇更新 `PATH` 環境變數,那麼安裝程式會將 `/opt/custompython/bin` 加入到 `PATH` 環境變數中。
+
+它看起來大致會是這樣:
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin
+```
+
+如此一來,當你在終端機輸入 `python` 時,系統會在 `/opt/custompython/bin` 中找到 Python 程式(最後一個目錄)並使用它。
+
+////
+
+//// tab | Windows
+
+假設你安裝了 Python,並將其安裝在目錄 `C:\opt\custompython\bin` 中。
+
+如果你選擇更新 `PATH` 環境變數(在 Python 安裝程式中,這個選項是名為 `Add Python x.xx to PATH` 的勾選框——譯者註),那麼安裝程式會將 `C:\opt\custompython\bin` 加入到 `PATH` 環境變數中。
+
+```plaintext
+C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin
+```
+
+如此一來,當你在終端機輸入 `python` 時,系統會在 `C:\opt\custompython\bin` 中找到 Python 程式(最後一個目錄)並使用它。
+
+////
+
+因此,如果你輸入:
+
+
+
+```console
+$ python
+```
+
+
+
+//// tab | Linux, macOS
+
+系統會在 `/opt/custompython/bin` 中**找到** `python` 程式並執行它。
+
+這大致等同於輸入以下指令:
+
+
+
+```console
+$ /opt/custompython/bin/python
+```
+
+
+
+////
+
+//// tab | Windows
+
+系統會在 `C:\opt\custompython\bin\python` 中**找到** `python` 程式並執行它。
+
+這大致等同於輸入以下指令:
+
+
+
+```console
+$ C:\opt\custompython\bin\python
+```
+
+
+
+////
+
+當學習[虛擬環境](virtual-environments.md)時,這些資訊將會很有用。
+
+## 結論
+
+透過這個教學,你應該對**環境變數**是什麼以及如何在 Python 中使用它們有了基本的了解。
+
+你也可以在
環境變數 - 維基百科 (
Wikipedia for Environment Variable) 中了解更多關於它們的資訊。
+
+在許多情況下,環境變數的用途和適用性可能不會立刻顯現。但是在開發過程中,它們會在許多不同的場景中出現,因此瞭解它們是非常必要的。
+
+例如,你在接下來的[虛擬環境](virtual-environments.md)章節中將需要這些資訊。
diff --git a/docs/zh-hant/docs/fastapi-cli.md b/docs/zh-hant/docs/fastapi-cli.md
new file mode 100644
index 000000000..3c644ce46
--- /dev/null
+++ b/docs/zh-hant/docs/fastapi-cli.md
@@ -0,0 +1,83 @@
+# FastAPI CLI
+
+**FastAPI CLI** 是一個命令列程式,能用來運行你的 FastAPI 應用程式、管理你的 FastAPI 專案等。
+
+當你安裝 FastAPI(例如使用 `pip install "fastapi[standard]"`),它會包含一個叫做 `fastapi-cli` 的套件,這個套件提供了 `fastapi` 命令。
+
+要運行你的 FastAPI 應用程式來進行開發,你可以使用 `fastapi dev` 命令:
+
+
+
+```console
+$ fastapi dev main.py
+INFO Using path main.py
+INFO Resolved absolute path /home/user/code/awesomeapp/main.py
+INFO Searching for package file structure from directories with __init__.py files
+INFO Importing from /home/user/code/awesomeapp
+
+ ╭─ Python module file ─╮
+ │ │
+ │ 🐍 main.py │
+ │ │
+ ╰──────────────────────╯
+
+INFO Importing module main
+INFO Found importable FastAPI app
+
+ ╭─ Importable FastAPI app ─╮
+ │ │
+ │ from main import app │
+ │ │
+ ╰──────────────────────────╯
+
+INFO Using import string main:app
+
+ ╭────────── FastAPI CLI - Development mode ───────────╮
+ │ │
+ │ Serving at: http://127.0.0.1:8000 │
+ │ │
+ │ API docs: http://127.0.0.1:8000/docs │
+ │ │
+ │ Running in development mode, for production use: │
+ │ │
+ │ fastapi run │
+ │ │
+ ╰─────────────────────────────────────────────────────╯
+
+INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp']
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [2265862] using WatchFiles
+INFO: Started server process [2265873]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+`fastapi` 命令列程式就是 **FastAPI CLI**。
+
+FastAPI CLI 接收你的 Python 程式路徑(例如 `main.py`),並自動檢測 FastAPI 實例(通常命名為 `app`),確定正確的引入模組流程,然後運行該應用程式。
+
+在生產環境,你應該使用 `fastapi run` 命令。 🚀
+
+**FastAPI CLI** 內部使用了
Uvicorn,這是一個高效能、適合生產環境的 ASGI 伺服器。 😎
+
+## `fastapi dev`
+
+執行 `fastapi dev` 會啟動開發模式。
+
+預設情況下,**auto-reload** 功能是啟用的,當你對程式碼進行修改時,伺服器會自動重新載入。這會消耗較多資源,並且可能比禁用時更不穩定。因此,你應該只在開發環境中使用此功能。它也會在 IP 位址 `127.0.0.1` 上監聽,這是用於你的機器與自身通訊的 IP 位址(`localhost`)。
+
+## `fastapi run`
+
+執行 `fastapi run` 會以生產模式啟動 FastAPI。
+
+預設情況下,**auto-reload** 功能是禁用的。它也會在 IP 位址 `0.0.0.0` 上監聽,表示會監聽所有可用的 IP 地址,這樣任何能與該機器通訊的人都可以公開存取它。這通常是你在生產環境中運行應用程式的方式,例如在容器中運行時。
+
+在大多數情況下,你會(也應該)有一個「終止代理」來處理 HTTPS,這取決於你如何部署你的應用程式,你的服務供應商可能會為你做這件事,或者你需要自己設置它。
+
+/// tip
+
+你可以在[部署文件](deployment/index.md){.internal-link target=_blank}中了解更多相關資訊。
+
+///
diff --git a/docs/zh-hant/docs/features.md b/docs/zh-hant/docs/features.md
new file mode 100644
index 000000000..3a1392b51
--- /dev/null
+++ b/docs/zh-hant/docs/features.md
@@ -0,0 +1,207 @@
+# 特性
+
+## FastAPI 特性
+
+**FastAPI** 提供了以下内容:
+
+### 建立在開放標準的基礎上
+
+* 使用
OpenAPI 來建立 API,包含
路徑操作、參數、請求內文、安全性等聲明。
+* 使用
JSON Schema(因為 OpenAPI 本身就是基於 JSON Schema)自動生成資料模型文件。
+* 經過縝密的研究後圍繞這些標準進行設計,而不是事後在已有系統上附加的一層功能。
+* 這也讓我們在多種語言中可以使用自動**用戶端程式碼生成**。
+
+### 能夠自動生成文件
+
+FastAPI 能生成互動式 API 文件和探索性的 Web 使用者介面。由於該框架基於 OpenAPI,因此有多種選擇,預設提供了兩種。
+
+*
Swagger UI 提供互動式探索,讓你可以直接從瀏覽器呼叫並測試你的 API 。
+
+
+
+*
ReDoc 提供結構性的文件,讓你可以在瀏覽器中查看。
+
+
+
+
+### 現代 Python
+
+這一切都基於標準的 **Python 型別**宣告(感謝 Pydantic)。無需學習新的語法,只需使用標準的現代 Python。
+
+如果你需要 2 分鐘來學習如何使用 Python 型別(即使你不使用 FastAPI),可以看看這個簡短的教學:[Python 型別](python-types.md){.internal-link target=_blank}。
+
+如果你寫帶有 Python 型別的程式碼:
+
+```python
+from datetime import date
+
+from pydantic import BaseModel
+
+# 宣告一個變數為 string
+# 並在函式中獲得 editor support
+def main(user_id: str):
+ return user_id
+
+
+# 宣告一個 Pydantic model
+class User(BaseModel):
+ id: int
+ name: str
+ joined: date
+```
+
+
+可以像這樣來使用:
+
+```python
+my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
+
+second_user_data = {
+ "id": 4,
+ "name": "Mary",
+ "joined": "2018-11-30",
+}
+
+my_second_user: User = User(**second_user_data)
+```
+
+
+/// info
+
+`**second_user_data` 意思是:
+
+將 `second_user_data` 字典直接作為 key-value 引數傳遞,等同於:`User(id=4, name="Mary", joined="2018-11-30")`
+
+///
+
+### 多種編輯器支援
+
+整個框架的設計是為了讓使用變得簡單且直觀,在開始開發之前,所有決策都在多個編輯器上進行了測試,以確保提供最佳的開發體驗。
+
+在最近的 Python 開發者調查中,我們能看到
被使用最多的功能是 autocompletion,此功能可以預測將要輸入文字,並自動補齊。
+
+整個 **FastAPI** 框架就是基於這一點,任何地方都可以進行自動補齊。
+
+你幾乎不需要經常來回看文件。
+
+在這裡,你的編輯器可能會這樣幫助你:
+
+*
Visual Studio Code 中:
+
+
+
+*
PyCharm 中:
+
+
+
+你將能進行程式碼補齊,這是在之前你可能曾認為不可能的事。例如,請求 JSON body(可能是巢狀的)中的鍵 `price`。
+
+這樣比較不會輸錯鍵名,不用來回翻看文件,也不用來回滾動尋找你最後使用的 `username` 或者 `user_name`。
+
+
+
+### 簡潔
+
+FastAPI 為你提供了**預設值**,讓你不必在初期進行繁瑣的配置,一切都可以自動運作。如果你有更具體的需求,則可以進行調整和自定義,
+
+但在大多數情況下,你只需要直接使用預設值,就能順利完成 API 開發。
+
+### 驗證
+
+所有的驗證都由完善且強大的 **Pydantic** 處理。
+
+* 驗證大部分(甚至所有?)的 Python **資料型別**,包括:
+ * JSON 物件 (`dict`)。
+ * JSON 陣列 (`list`) 定義項目型別。
+ * 字串 (`str`) 欄位,定義最小或最大長度。
+ * 數字 (`int`, `float`) 與其最大值和最小值等。
+
+* 驗證外來的型別,比如:
+ * URL
+ * Email
+ * UUID
+
+
+### 安全性及身份驗證
+
+FastAPI 已經整合了安全性和身份驗證的功能,但不會強制與特定的資料庫或資料模型進行綁定。
+
+OpenAPI 中定義的安全模式,包括:
+
+* HTTP 基本認證。
+* **OAuth2**(也使用 **JWT tokens**)。在 [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank} 查看教學。
+* API 密鑰,在:
+ * 標頭(Header)
+ * 查詢參數
+ * Cookies,等等。
+
+加上来自 Starlette(包括 **session cookie**)的所有安全特性。
+
+所有的這些都是可重複使用的工具和套件,可以輕鬆與你的系統、資料儲存(Data Stores)、關聯式資料庫(RDBMS)以及非關聯式資料庫(NoSQL)等等整合。
+
+
+### 依賴注入(Dependency Injection)
+
+FastAPI 有一個使用簡單,但是非常強大的
依賴注入系統。
+
+* 依賴項甚至可以有自己的依賴,從而形成一個層級或**依賴圖**的結構。
+* 所有**自動化處理**都由框架完成。
+* 依賴項不僅能從請求中提取資料,還能**對 API 的路徑操作進行強化**,並自動生成文檔。
+* 即使是依賴項中定義的*路徑操作參數*,也會**自動進行驗證**。
+* 支持複雜的用戶身份驗證系統、**資料庫連接**等。
+* 不與資料庫、前端等進行強制綁定,但能輕鬆整合它們。
+
+
+### 無限制「擴充功能」
+
+或者說,無需其他額外配置,直接導入並使用你所需要的程式碼。
+
+任何整合都被設計得非常簡單易用(通過依賴注入),你只需用與*路徑操作*相同的結構和語法,用兩行程式碼就能為你的應用程式建立一個「擴充功能」。
+
+
+### 測試
+
+* 100% 的
測試覆蓋率。
+* 100% 的程式碼有
型別註釋。
+* 已能夠在生產環境應用程式中使用。
+
+## Starlette 特性
+
+**FastAPI** 完全相容且基於
Starlette。所以,你有其他的 Starlette 程式碼也能正常運作。FastAPI 繼承了 Starlette 的所有功能,如果你已經知道或者使用過 Starlette,大部分的功能會以相同的方式運作。
+
+通過 **FastAPI** 你可以獲得所有 **Starlette** 的特性(FastAPI 就像加強版的 Starlette):
+
+* 性能極其出色。它是
Python 可用的最快框架之一,和 **NodeJS** 及 **Go** 相當。
+* **支援 WebSocket**。
+* 能在行程內處理背景任務。
+* 支援啟動和關閉事件。
+* 有基於 HTTPX 的測試用戶端。
+* 支援 **CORS**、GZip、靜態檔案、串流回應。
+* 支援 **Session 和 Cookie** 。
+* 100% 測試覆蓋率。
+* 100% 型別註釋的程式碼庫。
+
+## Pydantic 特性
+
+**FastAPI** 完全相容且基於
Pydantic。所以,你有其他 Pydantic 程式碼也能正常工作。
+
+相容包括基於 Pydantic 的外部函式庫, 例如用於資料庫的
ORMs,
ODMs。
+
+這也意味著在很多情況下,你可以把從請求中獲得的物件**直接傳到資料庫**,因為所有資料都會自動進行驗證。
+
+反之亦然,在很多情況下,你也可以把從資料庫中獲取的物件**直接傳給客戶端**。
+
+通過 **FastAPI** 你可以獲得所有 **Pydantic** 的特性(FastAPI 基於 Pydantic 做了所有的資料處理):
+
+* **更簡單**:
+ * 不需要學習新的 micro-language 來定義結構。
+ * 如果你知道 Python 型別,你就知道如何使用 Pydantic。
+* 和你的 **
IDE/
linter/brain** 都能好好配合:
+ * 因為 Pydantic 的資料結構其實就是你自己定義的類別實例,所以自動補齊、linting、mypy 以及你的直覺都能很好地在經過驗證的資料上發揮作用。
+* 驗證**複雜結構**:
+ * 使用 Pydantic 模型時,你可以把資料結構分層設計,並且用 Python 的 `List` 和 `Dict` 等型別來定義。
+ * 驗證器讓我們可以輕鬆地定義和檢查複雜的資料結構,並把它們轉換成 JSON Schema 進行記錄。
+ * 你可以擁有深層**巢狀的 JSON** 物件,並對它們進行驗證和註釋。
+* **可擴展**:
+ * Pydantic 讓我們可以定義客製化的資料型別,或者你可以使用帶有 validator 裝飾器的方法來擴展模型中的驗證功能。
+* 100% 測試覆蓋率。
diff --git a/docs/zh-hant/docs/how-to/index.md b/docs/zh-hant/docs/how-to/index.md
new file mode 100644
index 000000000..db740140d
--- /dev/null
+++ b/docs/zh-hant/docs/how-to/index.md
@@ -0,0 +1,13 @@
+# 使用指南 - 範例集
+
+在這裡,你將會看到**不同主題**的範例或「如何使用」的指南。
+
+大多數這些想法都是**獨立**的,在大多數情況下,你只需要研究那些直接適用於**你的專案**的東西。
+
+如果有些東西看起來很有趣且對你的專案很有用的話再去讀它,否則你可能可以跳過它們。
+
+/// tip
+
+如果你想要以結構化的方式**學習 FastAPI**(推薦),請前往[教學 - 使用者指南](../tutorial/index.md){.internal-link target=_blank}逐章閱讀。
+
+///
diff --git a/docs/zh-hant/docs/index.md b/docs/zh-hant/docs/index.md
new file mode 100644
index 000000000..81d99ede4
--- /dev/null
+++ b/docs/zh-hant/docs/index.md
@@ -0,0 +1,468 @@
+
+
+
+
+ FastAPI 框架,高效能,易於學習,快速開發,適用於生產環境
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+**文件**:
https://fastapi.tiangolo.com
+
+**程式碼**:
https://github.com/fastapi/fastapi
+
+---
+
+FastAPI 是一個現代、快速(高效能)的 web 框架,用於 Python 並採用標準 Python 型別提示。
+
+主要特點包含:
+
+- **快速**: 非常高的效能,可與 **NodeJS** 和 **Go** 效能相當 (歸功於 Starlette and Pydantic)。 [FastAPI 是最快的 Python web 框架之一](#performance)。
+- **極速開發**: 提高開發功能的速度約 200% 至 300%。 \*
+- **更少的 Bug**: 減少約 40% 的人為(開發者)導致的錯誤。 \*
+- **直覺**: 具有出色的編輯器支援,處處都有
自動補全以減少偵錯時間。
+- **簡單**: 設計上易於使用和學習,大幅減少閱讀文件的時間。
+- **簡潔**: 最小化程式碼重複性。可以通過不同的參數聲明來實現更豐富的功能,和更少的錯誤。
+- **穩健**: 立即獲得生產級可用的程式碼,還有自動生成互動式文件。
+- **標準化**: 基於 (且完全相容於) OpenAPIs 的相關標準:
OpenAPI(之前被稱為 Swagger)和
JSON Schema。
+
+
\* 基於內部開發團隊在建立生產應用程式時的測試預估。
+
+## 贊助
+
+
+
+{% if sponsors %}
+{% for sponsor in sponsors.gold -%}
+

+{% endfor -%}
+{%- for sponsor in sponsors.silver -%}
+

+{% endfor %}
+{% endif %}
+
+
+
+
其他贊助商
+
+## 評價
+
+"_[...] 近期大量的使用 **FastAPI**。 [...] 目前正在計畫在**微軟**團隊的**機器學習**服務中導入。其中一些正在整合到核心的 **Windows** 產品和一些 **Office** 產品。_"
+
+
Kabir Khan -
Microsoft (ref)
+
+---
+
+"_我們使用 **FastAPI** 來建立產生**預測**結果的 **REST** 伺服器。 [for Ludwig]_"
+
+
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala -
Uber (ref)
+
+---
+
+"_**Netflix** 很榮幸地宣布開源**危機管理**協調框架: **Dispatch**! [是使用 **FastAPI** 建構]_"
+
+
Kevin Glisson, Marc Vilanova, Forest Monsen -
Netflix (ref)
+
+---
+
+"_我對 **FastAPI** 興奮得不得了。它太有趣了!_"
+
+
+
+---
+
+"_老實說,你建造的東西看起來非常堅固和精緻。在很多方面,這就是我想要的,看到有人建造它真的很鼓舞人心。_"
+
+
+
+---
+
+"_如果您想學習一種用於構建 REST API 的**現代框架**,不能錯過 **FastAPI** [...] 它非常快速、且易於使用和學習 [...]_"
+
+"_我們的 **APIs** 已經改用 **FastAPI** [...] 我想你會喜歡它 [...]_"
+
+
+
+---
+
+"_如果有人想要建立一個生產環境的 Python API,我強烈推薦 **FastAPI**,它**設計精美**,**使用簡單**且**高度可擴充**,它已成為我們 API 優先開發策略中的**關鍵組件**,並且驅動了許多自動化服務,例如我們的 Virtual TAC Engineer。_"
+
+
Deon Pillsbury -
Cisco (ref)
+
+---
+
+## **Typer**,命令列中的 FastAPI
+
+

+
+如果你不是在開發網頁 API,而是正在開發一個在終端機中運行的
命令列應用程式,不妨嘗試
**Typer**。
+
+**Typer** 是 FastAPI 的小兄弟。他立志成為命令列的 **FastAPI**。 ⌨️ 🚀
+
+## 安裝需求
+
+FastAPI 是站在以下巨人的肩膀上:
+
+-
Starlette 負責網頁的部分
+-
Pydantic 負責資料的部分
+
+## 安裝
+
+
+
+```console
+$ pip install fastapi
+
+---> 100%
+```
+
+
+
+你同時也會需要 ASGI 伺服器用於生產環境,像是
Uvicorn 或
Hypercorn。
+
+
+
+```console
+$ pip install "uvicorn[standard]"
+
+---> 100%
+```
+
+
+
+## 範例
+
+### 建立
+
+- 建立一個 python 檔案 `main.py`,並寫入以下程式碼:
+
+```Python
+from typing import Union
+
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+def read_root():
+ return {"Hello": "World"}
+
+
+@app.get("/items/{item_id}")
+def read_item(item_id: int, q: Union[str, None] = None):
+ return {"item_id": item_id, "q": q}
+```
+
+
+或可以使用 async def
...
+
+如果你的程式使用 `async` / `await`,請使用 `async def`:
+
+```Python hl_lines="9 14"
+from typing import Union
+
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+async def read_root():
+ return {"Hello": "World"}
+
+
+@app.get("/items/{item_id}")
+async def read_item(item_id: int, q: Union[str, None] = None):
+ return {"item_id": item_id, "q": q}
+```
+
+**注意**:
+
+如果你不知道是否會用到,可以查看 _"In a hurry?"_ 章節中,關於 `async` 和 `await` 的部分。
+
+
+
+### 運行
+
+使用以下指令運行伺服器:
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [28720]
+INFO: Started server process [28722]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+
+關於指令 uvicorn main:app --reload
...
+
+該指令 `uvicorn main:app` 指的是:
+
+- `main`:`main.py` 檔案(一個 python 的 "模組")。
+- `app`:在 `main.py` 檔案中,使用 `app = FastAPI()` 建立的物件。
+- `--reload`:程式碼更改後會自動重新啟動,請僅在開發時使用此參數。
+
+
+
+### 檢查
+
+使用瀏覽器開啟
http://127.0.0.1:8000/items/5?q=somequery。
+
+你將會看到以下的 JSON 回應:
+
+```JSON
+{"item_id": 5, "q": "somequery"}
+```
+
+你已經建立了一個具有以下功能的 API:
+
+- 透過路徑 `/` 和 `/items/{item_id}` 接受 HTTP 請求。
+- 以上路經都接受 `GET`
請求(也被稱為 HTTP _方法_)。
+- 路徑 `/items/{item_id}` 有一個 `int` 型別的 `item_id` 參數。
+- 路徑 `/items/{item_id}` 有一個 `str` 型別的查詢參數 `q`。
+
+### 互動式 API 文件
+
+使用瀏覽器開啟
http://127.0.0.1:8000/docs。
+
+你會看到自動生成的互動式 API 文件(由
Swagger UI 生成):
+
+
+
+### ReDoc API 文件
+
+使用瀏覽器開啟
http://127.0.0.1:8000/redoc。
+
+你將看到 ReDoc 文件 (由
ReDoc 生成):
+
+
+
+## 範例升級
+
+現在繼續修改 `main.py` 檔案,來接收一個帶有 body 的 `PUT` 請求。
+
+我們使用 Pydantic 來使用標準的 Python 型別聲明請求。
+
+```Python hl_lines="4 9-12 25-27"
+from typing import Union
+
+from fastapi import FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ price: float
+ is_offer: Union[bool, None] = None
+
+
+@app.get("/")
+def read_root():
+ return {"Hello": "World"}
+
+
+@app.get("/items/{item_id}")
+def read_item(item_id: int, q: Union[str, None] = None):
+ return {"item_id": item_id, "q": q}
+
+
+@app.put("/items/{item_id}")
+def update_item(item_id: int, item: Item):
+ return {"item_name": item.name, "item_id": item_id}
+```
+
+伺服器將自動重新載入(因為在上一步中,你向 `uvicorn` 指令添加了 `--reload` 的選項)。
+
+### 互動式 API 文件升級
+
+使用瀏覽器開啟
http://127.0.0.1:8000/docs。
+
+- 互動式 API 文件會自動更新,並加入新的 body 請求:
+
+
+
+- 點擊 "Try it out" 按鈕, 你可以填寫參數並直接與 API 互動:
+
+
+
+- 然後點擊 "Execute" 按鈕,使用者介面將會向 API 發送請求,並將結果顯示在螢幕上:
+
+
+
+### ReDoc API 文件升級
+
+使用瀏覽器開啟
http://127.0.0.1:8000/redoc。
+
+- ReDoc API 文件會自動更新,並加入新的參數和 body 請求:
+
+
+
+### 總結
+
+總結來說, 你就像宣告函式的參數型別一樣,只宣告了一次請求參數和請求主體參數等型別。
+
+你使用 Python 標準型別來完成聲明。
+
+你不需要學習新的語法、類別、方法或函式庫等等。
+
+只需要使用 **Python 以上的版本**。
+
+舉個範例,比如宣告 int 的型別:
+
+```Python
+item_id: int
+```
+
+或是一個更複雜的 `Item` 模型:
+
+```Python
+item: Item
+```
+
+在進行一次宣告後,你將獲得:
+
+- 編輯器支援:
+ - 自動補全
+ - 型別檢查
+- 資料驗證:
+ - 驗證失敗時自動生成清楚的錯誤訊息
+ - 可驗證多層巢狀的 JSON 物件
+-
轉換輸入的資料: 轉換來自網路請求到 Python 資料型別。包含以下數據:
+ - JSON
+ - 路徑參數
+ - 查詢參數
+ - Cookies
+ - 請求標頭
+ - 表單
+ - 文件
+-
轉換輸出的資料: 轉換 Python 資料型別到網路傳輸的 JSON:
+ - 轉換 Python 型別 (`str`、 `int`、 `float`、 `bool`、 `list` 等)
+ - `datetime` 物件
+ - `UUID` 物件
+ - 數據模型
+ - ...還有其他更多
+- 自動生成的 API 文件,包含 2 種不同的使用介面:
+ - Swagger UI
+ - ReDoc
+
+---
+
+回到前面的的程式碼範例,**FastAPI** 還會:
+
+- 驗證 `GET` 和 `PUT` 請求路徑中是否包含 `item_id`。
+- 驗證 `GET` 和 `PUT` 請求中的 `item_id` 是否是 `int` 型別。
+ - 如果驗證失敗,將會返回清楚有用的錯誤訊息。
+- 查看 `GET` 請求中是否有命名為 `q` 的查詢參數 (例如 `http://127.0.0.1:8000/items/foo?q=somequery`)。
+ - 因為 `q` 參數被宣告為 `= None`,所以是選填的。
+ - 如果沒有宣告 `None`,則此參數將會是必填 (例如 `PUT` 範例的請求 body)。
+- 對於 `PUT` 的請求 `/items/{item_id}`,將會讀取 body 為 JSON:
+ - 驗證是否有必填屬性 `name` 且型別是 `str`。
+ - 驗證是否有必填屬性 `price` 且型別是 `float`。
+ - 驗證是否有選填屬性 `is_offer` 且型別是 `bool`。
+ - 以上驗證都適用於多層次巢狀 JSON 物件。
+- 自動轉換 JSON 格式。
+- 透過 OpenAPI 文件來記錄所有內容,可以被用於:
+ - 互動式文件系統。
+ - 自動為多種程式語言生成用戶端的程式碼。
+- 提供兩種交互式文件介面。
+
+---
+
+雖然我們只敘述了表面的功能,但其實你已經理解了它是如何執行。
+
+試著修改以下程式碼:
+
+```Python
+ return {"item_name": item.name, "item_id": item_id}
+```
+
+從:
+
+```Python
+ ... "item_name": item.name ...
+```
+
+修改為:
+
+```Python
+ ... "item_price": item.price ...
+```
+
+然後觀察你的編輯器,會自動補全並且還知道他們的型別:
+
+
+
+有關更多功能的完整範例,可以參考
教學 - 使用者指南。
+
+**劇透警告**: 教學 - 使用者指南內容有:
+
+- 對來自不同地方的**參數**進行宣告:像是 **headers**, **cookies**, **form 表單**以及**上傳檔案**。
+- 如何設定 **驗證限制** 像是 `maximum_length` or `regex`。
+- 簡單且非常容易使用的 **
依賴注入** 系統。
+- 安全性和身份驗證,包含提供支援 **OAuth2**、**JWT tokens** 和 **HTTP Basic** 驗證。
+- 更進階 (但同樣簡單) 的宣告 **多層次的巢狀 JSON 格式** (感謝 Pydantic)。
+- **GraphQL** 與
Strawberry 以及其他的相關函式庫進行整合。
+- 更多其他的功能 (感謝 Starlette) 像是:
+ - **WebSockets**
+ - 於 HTTPX 和 `pytest` 的非常簡單測試
+ - **CORS**
+ - **Cookie Sessions**
+ - ...以及更多
+
+## 效能
+
+來自獨立機構 TechEmpower 的測試結果,顯示在 Uvicorn 執行下的 **FastAPI** 是
最快的 Python 框架之一, 僅次於 Starlette 和 Uvicorn 本身 (兩者是 FastAPI 的底層)。 (\*)
+
+想了解更多訊息,可以參考
測試結果。
+
+## 可選的依賴套件
+
+用於 Pydantic:
+
+-
email-validator
- 用於電子郵件驗證。
+-
pydantic-settings
- 用於設定管理。
+-
pydantic-extra-types
- 用於與 Pydantic 一起使用的額外型別。
+
+用於 Starlette:
+
+-
httpx
- 使用 `TestClient`時必須安裝。
+-
jinja2
- 使用預設的模板配置時必須安裝。
+-
python-multipart
- 需要使用 `request.form()` 對表單進行
"解析" 時安裝。
+-
itsdangerous
- 需要使用 `SessionMiddleware` 支援時安裝。
+-
pyyaml
- 用於支援 Starlette 的 `SchemaGenerator` (如果你使用 FastAPI,可能不需要它)。
+
+用於 FastAPI / Starlette:
+
+-
uvicorn
- 用於加載和運行應用程式的服務器。
+-
orjson
- 使用 `ORJSONResponse`時必須安裝。
+-
ujson
- 使用 `UJSONResponse` 時必須安裝。
+
+你可以使用 `pip install "fastapi[all]"` 來安裝這些所有依賴套件。
+
+## 授權
+
+該項目遵循 MIT 許可協議。
diff --git a/docs/zh-hant/docs/learn/index.md b/docs/zh-hant/docs/learn/index.md
new file mode 100644
index 000000000..eb7d7096a
--- /dev/null
+++ b/docs/zh-hant/docs/learn/index.md
@@ -0,0 +1,5 @@
+# 學習
+
+以下是學習 FastAPI 的入門介紹和教學。
+
+你可以將其視為一本**書籍**或一門**課程**,這是**官方**認可並推薦的 FastAPI 學習方式。 😎
diff --git a/docs/zh-hant/docs/resources/index.md b/docs/zh-hant/docs/resources/index.md
new file mode 100644
index 000000000..f4c70a3a0
--- /dev/null
+++ b/docs/zh-hant/docs/resources/index.md
@@ -0,0 +1,3 @@
+# 資源
+
+額外的資源、外部連結、文章等。 ✈️
diff --git a/docs/zh-hant/docs/tutorial/first-steps.md b/docs/zh-hant/docs/tutorial/first-steps.md
new file mode 100644
index 000000000..a557fa369
--- /dev/null
+++ b/docs/zh-hant/docs/tutorial/first-steps.md
@@ -0,0 +1,331 @@
+# 第一步
+
+最簡單的 FastAPI 檔案可能看起來像這樣:
+
+{* ../../docs_src/first_steps/tutorial001.py *}
+
+將其複製到一個名為 `main.py` 的文件中。
+
+執行即時重新載入伺服器(live server):
+
+
+
+```console
+$ fastapi dev main.py
+INFO Using path main.py
+INFO Resolved absolute path /home/user/code/awesomeapp/main.py
+INFO Searching for package file structure from directories with __init__.py files
+INFO Importing from /home/user/code/awesomeapp
+
+ ╭─ Python module file ─╮
+ │ │
+ │ 🐍 main.py │
+ │ │
+ ╰──────────────────────╯
+
+INFO Importing module main
+INFO Found importable FastAPI app
+
+ ╭─ Importable FastAPI app ─╮
+ │ │
+ │ from main import app │
+ │ │
+ ╰──────────────────────────╯
+
+INFO Using import string main:app
+
+ ╭────────── FastAPI CLI - Development mode ───────────╮
+ │ │
+ │ Serving at: http://127.0.0.1:8000 │
+ │ │
+ │ API docs: http://127.0.0.1:8000/docs │
+ │ │
+ │ Running in development mode, for production use: │
+ │ │
+ │ fastapi run │
+ │ │
+ ╰─────────────────────────────────────────────────────╯
+
+INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp']
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [2265862] using WatchFiles
+INFO: Started server process [2265873]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+在輸出中,有一列類似於:
+
+```hl_lines="4"
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+那列顯示了你的應用程式正在本地端機器上運行的 URL。
+
+### 查看它
+
+在瀏覽器中打開
http://127.0.0.1:8000.
+
+你將看到如下的 JSON 回應:
+
+```JSON
+{"message": "Hello World"}
+```
+
+### 互動式 API 文件
+
+現在,前往
http://127.0.0.1:8000/docs.
+
+你將看到自動的互動式 API 文件(由
Swagger UI 提供):
+
+
+
+### 替代 API 文件
+
+現在,前往
http://127.0.0.1:8000/redoc.
+
+你將看到另一種自動文件(由
ReDoc 提供):
+
+
+
+### OpenAPI
+
+**FastAPI** 使用定義 API 的 **OpenAPI** 標準來生成一個 「schema」 與你的所有 API。
+
+#### 「Schema」
+
+「schema」是對某個事物的定義或描述。它並不是實作它的程式碼,而僅僅是一個抽象的描述。
+
+#### API 「schema」
+
+在這種情況下,
OpenAPI 是一個規範,它規定了如何定義 API 的 schema。
+
+這個 schema 定義包含了你的 API 路徑、可能接收的參數等內容。
+
+#### 資料 「schema」
+
+「schema」這個術語也可能指某些資料的結構,比如 JSON 內容的結構。
+
+在這種情況下,它指的是 JSON 的屬性、資料型別等。
+
+#### OpenAPI 和 JSON Schema
+
+OpenAPI 定義了 API 的 schema。這個 schema 包含了使用 **JSON Schema** 定義的資料,這是 JSON 資料 schema 的標準。
+
+#### 檢查 `openapi.json`
+
+如果你好奇原始的 OpenAPI schema 長什麼樣子,FastAPI 會自動生成一個包含所有 API 描述的 JSON (schema)。
+
+你可以直接在
http://127.0.0.1:8000/openapi.json 查看它。
+
+它會顯示一個 JSON,類似於:
+
+```JSON
+{
+ "openapi": "3.1.0",
+ "info": {
+ "title": "FastAPI",
+ "version": "0.1.0"
+ },
+ "paths": {
+ "/items/": {
+ "get": {
+ "responses": {
+ "200": {
+ "description": "Successful Response",
+ "content": {
+ "application/json": {
+
+
+
+...
+```
+
+#### OpenAPI 的用途
+
+OpenAPI schema 驅動了兩個互動式文件系統。
+
+而且有許多替代方案,所有這些都是基於 OpenAPI。你可以輕鬆地將任何這些替代方案添加到使用 **FastAPI** 建置的應用程式中。
+
+你也可以用它自動生成程式碼,讓前端、手機應用程式或物聯網設備等與你的 API 進行通訊。
+
+## 逐步回顧
+
+### 第一步:引入 `FastAPI`
+
+{* ../../docs_src/first_steps/tutorial001.py h1[1] *}
+
+`FastAPI` 是一個 Python 類別,提供所有 API 的全部功能。
+
+/// note | Technical Details
+
+`FastAPI` 是一個直接繼承自 `Starlette` 的類別。
+
+你同樣可以透過 `FastAPI` 來使用
Starlette 所有的功能。
+
+///
+
+### 第二步:建立一個 `FastAPI` 「實例」
+
+{* ../../docs_src/first_steps/tutorial001.py h1[3] *}
+
+這裡的 `app` 變數將會是 `FastAPI` 類別的「實例」。
+
+這將是你建立所有 API 的主要互動點。
+
+### 第三步:建立一個 *路徑操作*
+
+#### 路徑
+
+這裡的「路徑」指的是 URL 中自第一個 `/` 以後的部分。
+
+例如,在 URL 中:
+
+```
+https://example.com/items/foo
+```
+
+……的路徑將會是:
+
+```
+/items/foo
+```
+
+/// info
+
+「路徑」也常被稱為「端點 endpoint」或「路由 route」。
+
+///
+
+在建置 API 時,「路徑」是分離「關注點」和「資源」的主要方式。
+
+#### 操作
+
+這裡的「操作」指的是 HTTP 的「方法」之一。
+
+其中包括:
+
+* `POST`
+* `GET`
+* `PUT`
+* `DELETE`
+
+……以及更少見的:
+
+* `OPTIONS`
+* `HEAD`
+* `PATCH`
+* `TRACE`
+
+在 HTTP 協定中,你可以使用這些「方法」之一(或更多)與每個路徑進行通信。
+
+---
+
+在建置 API 時,你通常使用這些特定的 HTTP 方法來執行特定的動作。
+
+通常你使用:
+
+* `POST`:用來建立資料。
+* `GET`:用來讀取資料。
+* `PUT`:用來更新資料。
+* `DELETE`:用來刪除資料。
+
+所以,在 OpenAPI 中,每個 HTTP 方法都被稱為「操作」。
+
+我們將會稱它們為「**操作**」。
+
+#### 定義一個 *路徑操作裝飾器*
+
+{* ../../docs_src/first_steps/tutorial001.py h1[6] *}
+
+`@app.get("/")` 告訴 **FastAPI** 那個函式負責處理請求:
+
+* 路徑 `/`
+* 使用
get
操作
+
+/// info | `@decorator` Info
+
+Python 中的 `@something` 語法被稱為「裝飾器」。
+
+你把它放在一個函式上面。像一個漂亮的裝飾帽子(我猜這是術語的來源)。
+
+一個「裝飾器」會對下面的函式做一些事情。
+
+在這種情況下,這個裝飾器告訴 **FastAPI** 那個函式對應於 **路徑** `/` 和 **操作** `get`.
+
+這就是「**路徑操作裝飾器**」。
+
+///
+
+你也可以使用其他的操作:
+
+* `@app.post()`
+* `@app.put()`
+* `@app.delete()`
+
+以及更少見的:
+
+* `@app.options()`
+* `@app.head()`
+* `@app.patch()`
+* `@app.trace()`
+
+/// tip
+
+你可以自由地使用每個操作(HTTP 方法)。
+
+**FastAPI** 不強制任何特定的意義。
+
+這裡的資訊作為一個指南,而不是要求。
+
+例如,當使用 GraphQL 時,你通常只使用 `POST` 操作。
+
+///
+
+### 第四步:定義 **路徑操作函式**
+
+這是我們的「**路徑操作函式**」:
+
+* **path**: 是 `/`.
+* **operation**: 是 `get`.
+* **function**: 是裝飾器下面的函式(在 `@app.get("/")` 下面)。
+
+{* ../../docs_src/first_steps/tutorial001.py h1[7] *}
+
+這就是一個 Python 函式。
+
+它將會在 **FastAPI** 收到一個請求時被呼叫,使用 `GET` 操作。
+
+在這種情況下,它是一個 `async` 函式。
+
+---
+
+你可以將它定義為一個正常的函式,而不是 `async def`:
+
+{* ../../docs_src/first_steps/tutorial003.py h1[7] *}
+
+/// note
+
+如果你不知道差別,請查看 [Async: *"In a hurry?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
+
+///
+
+### 第五步:回傳內容
+
+{* ../../docs_src/first_steps/tutorial001.py h1[8] *}
+
+你可以返回一個 `dict`、`list`、單個值作為 `str`、`int` 等。
+
+你也可以返回 Pydantic 模型(稍後你會看到更多關於這方面的內容)。
+
+有很多其他物件和模型會自動轉換為 JSON(包括 ORMs,等等)。試用你最喜歡的,很有可能它們已經有支援。
+
+## 回顧
+
+* 引入 `FastAPI`.
+* 建立一個 `app` 實例。
+* 寫一個 **路徑操作裝飾器** 使用裝飾器像 `@app.get("/")`。
+* 定義一個 **路徑操作函式**;例如,`def root(): ...`。
+* 使用命令 `fastapi dev` 執行開發伺服器。
diff --git a/docs/zh-hant/docs/tutorial/index.md b/docs/zh-hant/docs/tutorial/index.md
new file mode 100644
index 000000000..ae0056f52
--- /dev/null
+++ b/docs/zh-hant/docs/tutorial/index.md
@@ -0,0 +1,102 @@
+# 教學 - 使用者指南
+
+本教學將一步一步展示如何使用 **FastAPI** 及其大多數功能。
+
+每個部分都是在前一部分的基礎上逐步建置的,但內容結構是按主題分開的,因此你可以直接跳到任何特定的部分,解決你具體的 API 需求。
+
+它也被設計成可作為未來的參考,讓你隨時回來查看所需的內容。
+
+## 運行程式碼
+
+所有程式碼區塊都可以直接複製和使用(它們實際上是經過測試的 Python 檔案)。
+
+要運行任何範例,請將程式碼複製到 `main.py` 檔案,並使用以下命令啟動 `fastapi dev`:
+
+
+
+```console
+$ fastapi dev main.py
+INFO Using path main.py
+INFO Resolved absolute path /home/user/code/awesomeapp/main.py
+INFO Searching for package file structure from directories with __init__.py files
+INFO Importing from /home/user/code/awesomeapp
+
+ ╭─ Python module file ─╮
+ │ │
+ │ 🐍 main.py │
+ │ │
+ ╰──────────────────────╯
+
+INFO Importing module main
+INFO Found importable FastAPI app
+
+ ╭─ Importable FastAPI app ─╮
+ │ │
+ │ from main import app │
+ │ │
+ ╰──────────────────────────╯
+
+INFO Using import string main:app
+
+ ╭────────── FastAPI CLI - Development mode ───────────╮
+ │ │
+ │ Serving at: http://127.0.0.1:8000 │
+ │ │
+ │ API docs: http://127.0.0.1:8000/docs │
+ │ │
+ │ Running in development mode, for production use: │
+ │ │
+ │ fastapi run │
+ │ │
+ ╰─────────────────────────────────────────────────────╯
+
+INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp']
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [2265862] using WatchFiles
+INFO: Started server process [2265873]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+
+```
+
+
+
+**強烈建議**你編寫或複製程式碼、進行修改並在本地端運行。
+
+在編輯器中使用它,才能真正體會到 FastAPI 的好處,可以看到你只需編寫少量程式碼,以及所有的型別檢查、自動補齊等功能。
+
+---
+
+## 安裝 FastAPI
+
+第一步是安裝 FastAPI。
+
+確保你建立一個[虛擬環境](../virtual-environments.md){.internal-link target=_blank},啟用它,然後**安裝 FastAPI**:
+
+
+
+```console
+$ pip install "fastapi[standard]"
+
+---> 100%
+```
+
+
+
+/// note
+
+當你使用 `pip install "fastapi[standard]"` 安裝時,會包含一些預設的可選標準依賴項。
+
+如果你不想包含那些可選的依賴項,你可以使用 `pip install fastapi` 來安裝。
+
+///
+
+## 進階使用者指南
+
+還有一個**進階使用者指南**你可以稍後閱讀。
+
+**進階使用者指南**建立在這個教學之上,使用相同的概念,並教你一些額外的功能。
+
+但首先你應該閱讀**教學 - 使用者指南**(你正在閱讀的內容)。
+
+它被設計成你可以使用**教學 - 使用者指南**來建立一個完整的應用程式,然後根據你的需求,使用一些額外的想法來擴展它。
diff --git a/docs/zh-hant/docs/tutorial/query-param-models.md b/docs/zh-hant/docs/tutorial/query-param-models.md
new file mode 100644
index 000000000..76ee74016
--- /dev/null
+++ b/docs/zh-hant/docs/tutorial/query-param-models.md
@@ -0,0 +1,68 @@
+# 查詢參數模型
+
+如果你有一組具有相關性的**查詢參數**,你可以建立一個 **Pydantic 模型**來聲明它們。
+
+這將允許你在**多個地方**去**重複使用模型**,並且一次性為所有參數聲明驗證和元資料 (metadata)。😎
+
+/// note
+
+FastAPI 從 `0.115.0` 版本開始支援這個特性。🤓
+
+///
+
+## 使用 Pydantic 模型的查詢參數
+
+在一個 **Pydantic 模型**中聲明你需要的**查詢參數**,然後將參數聲明為 `Query`:
+
+{* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *}
+
+**FastAPI** 將會從請求的**查詢參數**中**提取**出**每個欄位**的資料,並將其提供給你定義的 Pydantic 模型。
+
+## 查看文件
+
+你可以在 `/docs` 頁面的 UI 中查看查詢參數:
+
+
+

+
+
+## 禁止額外的查詢參數
+
+在一些特殊的使用場景中(可能不是很常見),你可能希望**限制**你要收到的查詢參數。
+
+你可以使用 Pydantic 的模型設定來 `forbid`(禁止)任何 `extra`(額外)欄位:
+
+{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *}
+
+如果客戶端嘗試在**查詢參數**中發送一些**額外的**資料,他們將會收到一個**錯誤**回應。
+
+例如,如果客戶端嘗試發送一個值為 `plumbus` 的 `tool` 查詢參數,如:
+
+```http
+https://example.com/items/?limit=10&tool=plumbus
+```
+
+他們將收到一個**錯誤**回應,告訴他們查詢參數 `tool` 是不允許的:
+
+```json
+{
+ "detail": [
+ {
+ "type": "extra_forbidden",
+ "loc": ["query", "tool"],
+ "msg": "Extra inputs are not permitted",
+ "input": "plumbus"
+ }
+ ]
+}
+```
+
+## 總結
+
+你可以使用 **Pydantic 模型**在 **FastAPI** 中聲明**查詢參數**。😎
+
+/// tip
+
+劇透警告:你也可以使用 Pydantic 模型來聲明 cookie 和 headers,但你將在本教學的後面部分閱讀到這部分內容。🤫
+
+///
diff --git a/docs/zh-hant/docs/virtual-environments.md b/docs/zh-hant/docs/virtual-environments.md
new file mode 100644
index 000000000..d8e31e08e
--- /dev/null
+++ b/docs/zh-hant/docs/virtual-environments.md
@@ -0,0 +1,844 @@
+# 虛擬環境
+
+當你在 Python 專案中工作時,你可能會需要使用一個**虛擬環境**(或類似的機制)來隔離你為每個專案安裝的套件。
+
+/// info
+
+如果你已經了解虛擬環境,知道如何建立和使用它們,你可以考慮跳過這一部分。🤓
+
+///
+
+/// tip
+
+**虛擬環境**和**環境變數**是不同的。
+
+**環境變數**是系統中的一個變數,可以被程式使用。
+
+**虛擬環境**是一個包含一些檔案的目錄。
+
+///
+
+/// info
+
+這個頁面將教你如何使用**虛擬環境**以及了解它們的工作原理。
+
+如果你計畫使用一個**可以為你管理一切的工具**(包括安裝 Python),試試
uv。
+
+///
+
+## 建立一個專案
+
+首先,為你的專案建立一個目錄。
+
+我(指原作者 —— 譯者注)通常會在我的主目錄下建立一個名為 `code` 的目錄。
+
+在這個目錄下,我再為每個專案建立一個目錄。
+
+
+
+```console
+// 進入主目錄
+$ cd
+// 建立一個用於存放所有程式碼專案的目錄
+$ mkdir code
+// 進入 code 目錄
+$ cd code
+// 建立一個用於存放這個專案的目錄
+$ mkdir awesome-project
+// 進入這個專案的目錄
+$ cd awesome-project
+```
+
+
+
+## 建立一個虛擬環境
+
+在開始一個 Python 專案的**第一時間**,**
在你的專案內部**建立一個虛擬環境。
+
+/// tip
+
+你只需要**在每個專案中操作一次**,而不是每次工作時都操作。
+
+///
+
+//// tab | `venv`
+
+你可以使用 Python 自帶的 `venv` 模組來建立一個虛擬環境。
+
+
+
+```console
+$ python -m venv .venv
+```
+
+
+
+/// details | 上述命令的含義
+
+* `python`: 使用名為 `python` 的程式
+* `-m`: 以腳本的方式呼叫一個模組,我們將告訴它接下來使用哪個模組
+* `venv`: 使用名為 `venv` 的模組,這個模組通常隨 Python 一起安裝
+* `.venv`: 在新目錄 `.venv` 中建立虛擬環境
+
+///
+
+////
+
+//// tab | `uv`
+
+如果你安裝了
`uv`,你也可以使用它來建立一個虛擬環境。
+
+
+
+```console
+$ uv venv
+```
+
+
+
+/// tip
+
+預設情況下,`uv` 會在一個名為 `.venv` 的目錄中建立一個虛擬環境。
+
+但你可以透過傳遞一個額外的引數來自訂它,指定目錄的名稱。
+
+///
+
+////
+
+這個命令會在一個名為 `.venv` 的目錄中建立一個新的虛擬環境。
+
+/// details | `.venv`,或是其他名稱
+
+你可以在不同的目錄下建立虛擬環境,但通常我們會把它命名為 `.venv`。
+
+///
+
+## 啟動虛擬環境
+
+啟動新的虛擬環境來確保你運行的任何 Python 指令或安裝的套件都能使用到它。
+
+/// tip
+
+**每次**開始一個**新的終端會話**來在這個專案工作時,你都需要執行這個操作。
+
+///
+
+//// tab | Linux, macOS
+
+
+
+```console
+$ source .venv/bin/activate
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ .venv\Scripts\Activate.ps1
+```
+
+
+
+////
+
+//// tab | Windows Bash
+
+或者,如果你在 Windows 上使用 Bash(例如
Git Bash):
+
+
+
+```console
+$ source .venv/Scripts/activate
+```
+
+
+
+////
+
+/// tip
+
+每次你在這個環境中安裝一個**新的套件**時,都需要**重新啟動**這個環境。
+
+這麼做確保了當你使用一個由這個套件安裝的**終端(
CLI)程式**時,你使用的是你的虛擬環境中的程式,而不是全域安裝、可能版本不同的程式。
+
+///
+
+## 檢查虛擬環境是否啟動
+
+檢查虛擬環境是否啟動(前面的指令是否生效)。
+
+/// tip
+
+這是**非必需的**,但這是一個很好的方法,可以**檢查**一切是否按預期工作,以及你是否使用了你打算使用的虛擬環境。
+
+///
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+
+
+如果它顯示了在你專案(在這個例子中是 `awesome-project`)的 `.venv/bin/python` 中的 `python` 二進位檔案,那麼它就生效了。🎉
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ Get-Command python
+
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+
+
+如果它顯示了在你專案(在這個例子中是 `awesome-project`)的 `.venv\Scripts\python` 中的 `python` 二進位檔案,那麼它就生效了。🎉
+
+////
+
+## 升級 `pip`
+
+/// tip
+
+如果你使用
`uv` 來安裝內容,而不是 `pip`,那麼你就不需要升級 `pip`。😎
+
+///
+
+如果你使用 `pip` 來安裝套件(它是 Python 的預設元件),你應該將它**升級**到最新版本。
+
+在安裝套件時出現的許多奇怪的錯誤都可以透過先升級 `pip` 來解決。
+
+/// tip
+
+通常你只需要在建立虛擬環境後**執行一次**這個操作。
+
+///
+
+確保虛擬環境是啟動的(使用上面的指令),然後運行:
+
+
+
+```console
+$ python -m pip install --upgrade pip
+
+---> 100%
+```
+
+
+
+## 加入 `.gitignore`
+
+如果你使用 **Git**(這是你應該使用的),加入一個 `.gitignore` 檔案來排除你的 `.venv` 中的所有內容。
+
+/// tip
+
+如果你使用
`uv` 來建立虛擬環境,它會自動為你完成這個操作,你可以跳過這一步。😎
+
+///
+
+/// tip
+
+通常你只需要在建立虛擬環境後**執行一次**這個操作。
+
+///
+
+
+
+```console
+$ echo "*" > .venv/.gitignore
+```
+
+
+
+/// details | 上述指令的含義
+
+- `echo "*"`: 將在終端中「顯示」文本 `*`(接下來的部分會對這個操作進行一些修改)
+- `>`: 使左邊的指令顯示到終端的任何內容實際上都不會被顯示,而是會被寫入到右邊的檔案中
+- `.gitignore`: 被寫入文本的檔案的名稱
+
+而 `*` 對於 Git 來說意味著「所有內容」。所以,它會忽略 `.venv` 目錄中的所有內容。
+
+該指令會建立一個名為 .gitignore 的檔案,內容如下:
+
+```gitignore
+*
+```
+
+///
+
+## 安裝套件
+
+在啟用虛擬環境後,你可以在其中安裝套件。
+
+/// tip
+
+當你需要安裝或升級套件時,執行本操作**一次**;
+
+如果你需要再升級版本或新增套件,你可以**再次執行此操作**。
+
+///
+
+### 直接安裝套件
+
+如果你急於安裝,不想使用檔案來聲明專案的套件依賴,你可以直接安裝它們。
+
+/// tip
+
+將程式所需的套件及其版本放在檔案中(例如 `requirements.txt` 或 `pyproject.toml`)是個好(而且非常好)的主意。
+
+///
+
+//// tab | `pip`
+
+
+
+```console
+$ pip install "fastapi[standard]"
+
+---> 100%
+```
+
+
+
+////
+
+//// tab | `uv`
+
+如果你有
`uv`:
+
+
+
+```console
+$ uv pip install "fastapi[standard]"
+---> 100%
+```
+
+
+
+////
+
+### 從 `requirements.txt` 安裝
+
+如果你有一個 `requirements.txt` 檔案,你可以使用它來安裝其中的套件。
+
+//// tab | `pip`
+
+
+
+```console
+$ pip install -r requirements.txt
+---> 100%
+```
+
+
+
+////
+
+//// tab | `uv`
+
+如果你有
`uv`:
+
+
+
+```console
+$ uv pip install -r requirements.txt
+---> 100%
+```
+
+
+
+////
+
+/// details | 關於 `requirements.txt`
+
+一個包含一些套件的 `requirements.txt` 檔案看起來應該是這樣的:
+
+```requirements.txt
+fastapi[standard]==0.113.0
+pydantic==2.8.0
+```
+
+///
+
+## 執行程式
+
+在啟用虛擬環境後,你可以執行你的程式,它將使用虛擬環境中的 Python 和你在其中安裝的套件。
+
+
+
+```console
+$ python main.py
+
+Hello World
+```
+
+
+
+## 設定編輯器
+
+你可能會用到編輯器,請確保設定它使用你建立的相同虛擬環境(它可能會自動偵測到),以便你可以獲得自動完成和内嵌錯誤提示。
+
+例如:
+
+*
VS Code
+*
PyCharm
+
+/// tip
+
+通常你只需要在建立虛擬環境時執行此操作**一次**。
+
+///
+
+## 退出虛擬環境
+
+當你完成工作後,你可以**退出**虛擬環境。
+
+
+
+```console
+$ deactivate
+```
+
+
+
+這樣,當你執行 `python` 時它不會嘗試從已安裝套件的虛擬環境中執行。
+
+## 開始工作
+
+現在你已經準備好開始你的工作了。
+
+
+
+/// tip
+
+你想要理解上面的所有內容嗎?
+
+繼續閱讀。👇🤓
+
+///
+
+## 為什麼要使用虛擬環境
+
+你需要安裝
Python 才能使用 FastAPI。
+
+接下來,你需要**安裝** FastAPI 以及你想使用的其他**套件**。
+
+要安裝套件,你通常會使用隨 Python 一起提供的 `pip` 指令(或類似的替代工具)。
+
+然而,如果你直接使用 `pip`,套件將會安裝在你的**全域 Python 環境**中(即 Python 的全域安裝)。
+
+### 存在的問題
+
+那麼,在全域 Python 環境中安裝套件有什麼問題呢?
+
+有時候,你可能會開發許多不同的程式,而這些程式各自依賴於**不同的套件**;有些專案甚至需要依賴於**相同套件的不同版本**。😱
+
+例如,你可能會建立一個名為 `philosophers-stone` 的專案,這個程式依賴於另一個名為 **`harry` 的套件,並使用版本 `1`**。因此,你需要安裝 `harry`。
+
+```mermaid
+flowchart LR
+ stone(philosophers-stone) -->|需要| harry-1[harry v1]
+```
+
+然而,在此之後,你又建立了另一個名為 `prisoner-of-azkaban` 的專案,而這個專案也依賴於 `harry`,但需要的是 **`harry` 版本 `3`**。
+
+```mermaid
+flowchart LR
+ azkaban(prisoner-of-azkaban) --> |需要| harry-3[harry v3]
+```
+
+現在的問題是,如果你在全域環境中安裝套件而不是在本地**虛擬環境**中,你將面臨選擇安裝哪個版本的 `harry` 的困境。
+
+如果你想運行 `philosophers-stone`,你需要先安裝 `harry` 版本 `1`,例如:
+
+
+
+```console
+$ pip install "harry==1"
+```
+
+
+
+然後你會在全域 Python 環境中安裝 `harry` 版本 `1`。
+
+```mermaid
+flowchart LR
+ subgraph global[全域環境]
+ harry-1[harry v1]
+ end
+ subgraph stone-project[專案 philosophers-stone]
+ stone(philosophers-stone) -->|需要| harry-1
+ end
+```
+
+但如果你想運行 `prisoner-of-azkaban`,你需要解除安裝 `harry` 版本 `1` 並安裝 `harry` 版本 `3`(或者只要你安裝版本 `3`,版本 `1` 就會自動移除)。
+
+
+
+```console
+$ pip install "harry==3"
+```
+
+
+
+於是,你在全域 Python 環境中安裝了 `harry` 版本 `3`。
+
+如果你再次嘗試運行 `philosophers-stone`,很可能會**無法正常運作**,因為它需要的是 `harry` 版本 `1`。
+
+```mermaid
+flowchart LR
+ subgraph global[全域環境]
+ harry-1[
harry v1]
+ style harry-1 fill:#ccc,stroke-dasharray: 5 5
+ harry-3[harry v3]
+ end
+ subgraph stone-project[專案 philosophers-stone]
+ stone(philosophers-stone) -.-x|⛔️| harry-1
+ end
+ subgraph azkaban-project[專案 prisoner-of-azkaban]
+ azkaban(prisoner-of-azkaban) --> |需要| harry-3
+ end
+```
+
+/// tip
+
+Python 套件在推出**新版本**時通常會儘量**避免破壞性更改**,但最好還是要謹慎,在安裝新版本前進行測試,以確保一切能正常運行。
+
+///
+
+現在,想像一下如果有**許多**其他**套件**,它們都是你的**專案所依賴的**。這樣是非常難以管理的。你可能會發現有些專案使用了一些**不相容的套件版本**,而無法得知為什麼某些程式無法正常運作。
+
+此外,取決於你的操作系統(例如 Linux、Windows、macOS),它可能已經預先安裝了 Python。在這種情況下,它可能已經有一些系統所需的套件和特定版本。如果你在全域 Python 環境中安裝套件,可能會**破壞**某些隨作業系統一起安裝的程式。
+
+## 套件安裝在哪裡
+
+當你安裝 Python 時,它會在你的電腦中建立一些目錄並放置一些檔案。
+
+其中一些目錄專門用來存放你所安裝的所有套件。
+
+當你運行:
+
+
+
+```console
+// 先別去運行這個指令,這只是個示例 🤓
+$ pip install "fastapi[standard]"
+---> 100%
+```
+
+
+
+這會從
PyPI 下載一個壓縮檔案,其中包含 FastAPI 的程式碼。
+
+它還會**下載** FastAPI 所依賴的其他套件的檔案。
+
+接著,它會**解壓**所有這些檔案,並將它們放在你的電腦中的某個目錄中。
+
+預設情況下,這些下載和解壓的檔案會放置於隨 Python 安裝的目錄中,即**全域環境**。
+
+## 什麼是虛擬環境
+
+解決套件都安裝在全域環境中的問題方法是為你所做的每個專案使用一個**虛擬環境**。
+
+虛擬環境是一個**目錄**,與全域環境非常相似,你可以在其中針對某個專案安裝套件。
+
+這樣,每個專案都會有自己的虛擬環境(`.venv` 目錄),其中包含自己的套件。
+
+```mermaid
+flowchart TB
+ subgraph stone-project[專案 philosophers-stone]
+ stone(philosophers-stone) --->|需要| harry-1
+ subgraph venv1[.venv]
+ harry-1[harry v1]
+ end
+ end
+ subgraph azkaban-project[專案 prisoner-of-azkaban]
+ azkaban(prisoner-of-azkaban) --->|需要| harry-3
+ subgraph venv2[.venv]
+ harry-3[harry v3]
+ end
+ end
+ stone-project ~~~ azkaban-project
+```
+
+## 啟用虛擬環境意味著什麼
+
+當你啟用了虛擬環境,例如:
+
+//// tab | Linux, macOS
+
+
+
+```console
+$ source .venv/bin/activate
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ .venv\Scripts\Activate.ps1
+```
+
+
+
+////
+
+//// tab | Windows Bash
+
+或者如果你在 Windows 上使用 Bash(例如
Git Bash):
+
+
+
+```console
+$ source .venv/Scripts/activate
+```
+
+
+
+////
+
+這個命令會建立或修改一些[環境變數](environment-variables.md){.internal-link target=_blank},這些環境變數將在接下來的指令中可用。
+
+其中之一是 `PATH` 變數。
+
+/// tip
+
+你可以在 [環境變數](environment-variables.md#path-environment-variable){.internal-link target=_blank} 部分了解更多關於 `PATH` 環境變數的內容。
+
+///
+
+啟用虛擬環境會將其路徑 `.venv/bin`(在 Linux 和 macOS 上)或 `.venv\Scripts`(在 Windows 上)加入到 `PATH` 環境變數中。
+
+假設在啟用環境之前,`PATH` 變數看起來像這樣:
+
+//// tab | Linux, macOS
+
+```plaintext
+/usr/bin:/bin:/usr/sbin:/sbin
+```
+
+這意味著系統會在以下目錄中查找程式:
+
+* `/usr/bin`
+* `/bin`
+* `/usr/sbin`
+* `/sbin`
+
+////
+
+//// tab | Windows
+
+```plaintext
+C:\Windows\System32
+```
+
+這意味著系統會在以下目錄中查找程式:
+
+* `C:\Windows\System32`
+
+////
+
+啟用虛擬環境後,`PATH` 變數會變成這樣:
+
+//// tab | Linux, macOS
+
+```plaintext
+/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin
+```
+
+這意味著系統現在會首先在以下目錄中查找程式:
+
+```plaintext
+/home/user/code/awesome-project/.venv/bin
+```
+
+然後再在其他目錄中查找。
+
+因此,當你在終端機中輸入 `python` 時,系統會在以下目錄中找到 Python 程式:
+
+```plaintext
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+並使用這個。
+
+////
+
+//// tab | Windows
+
+```plaintext
+C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32
+```
+
+這意味著系統現在會首先在以下目錄中查找程式:
+
+```plaintext
+C:\Users\user\code\awesome-project\.venv\Scripts
+```
+
+然後再在其他目錄中查找。
+
+因此,當你在終端機中輸入 `python` 時,系統會在以下目錄中找到 Python 程式:
+
+```plaintext
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+並使用這個。
+
+////
+
+一個重要的細節是,虛擬環境路徑會被放在 `PATH` 變數的**開頭**。系統會在找到任何其他可用的 Python **之前**找到它。這樣,當你運行 `python` 時,它會使用**虛擬環境中的** Python,而不是任何其他 `python`(例如,全域環境中的 `python`)。
+
+啟用虛擬環境還會改變其他一些內容,但這是它所做的最重要的事情之一。
+
+## 檢查虛擬環境
+
+當你檢查虛擬環境是否啟動時,例如:
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ Get-Command python
+
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+
+
+////
+
+這表示將使用的 `python` 程式是**在虛擬環境中**的那一個。
+
+在 Linux 和 macOS 中使用 `which`,在 Windows PowerShell 中使用 `Get-Command`。
+
+這個指令的運作方式是,它會在 `PATH` 環境變數中搜尋,依序**逐個路徑**查找名為 `python` 的程式。一旦找到,它會**顯示該程式的路徑**。
+
+最重要的是,當你呼叫 `python` 時,將執行的就是這個確切的 "`python`"。
+
+因此,你可以確認是否在正確的虛擬環境中。
+
+/// tip
+
+啟動一個虛擬環境,取得一個 Python,然後**切換到另一個專案**是件很容易的事;
+
+但如果第二個專案**無法正常運作**,那可能是因為你使用了來自其他專案的虛擬環境的、**不正確的 Python**。
+
+因此,檢查正在使用的 `python` 是非常實用的。🤓
+
+///
+
+## 為什麼要停用虛擬環境
+
+例如,你可能正在一個專案 `philosophers-stone` 上工作,**啟動了該虛擬環境**,安裝了套件並使用了該環境,
+
+然後你想要在**另一個專案** `prisoner-of-azkaban` 上工作,
+
+你進入那個專案:
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+```
+
+
+
+如果你不去停用 `philosophers-stone` 的虛擬環境,當你在終端中執行 `python` 時,它會嘗試使用 `philosophers-stone` 中的 Python。
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+
+$ python main.py
+
+// 匯入 sirius 錯誤,未安裝 😱
+Traceback (most recent call last):
+ File "main.py", line 1, in
+ import sirius
+```
+
+
+
+但如果你停用虛擬環境並啟用 `prisoner-of-askaban` 的新虛擬環境,那麼當你執行 `python` 時,它會使用 `prisoner-of-askaban` 中虛擬環境的 Python。
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+
+// 你不需要在舊目錄中操作停用,你可以在任何地方操作停用,甚至在切換到另一個專案之後 😎
+$ deactivate
+
+// 啟用 prisoner-of-azkaban/.venv 中的虛擬環境 🚀
+$ source .venv/bin/activate
+
+// 現在當你執行 python 時,它會在這個虛擬環境中找到已安裝的 sirius 套件 ✨
+$ python main.py
+
+I solemnly swear 🐺
+```
+
+
+
+## 替代方案
+
+這是一個簡單的指南,幫助你入門並教會你如何理解一切**底層**的原理。
+
+有許多**替代方案**來管理虛擬環境、套件依賴(requirements)、專案。
+
+當你準備好並想要使用一個工具來**管理整個專案**、套件依賴、虛擬環境等,建議你嘗試
uv。
+
+`uv` 可以執行許多操作,它可以:
+
+* 為你**安裝 Python**,包括不同的版本
+* 為你的專案管理**虛擬環境**
+* 安裝**套件**
+* 為你的專案管理套件的**依賴和版本**
+* 確保你有一個**精確**的套件和版本集合來安裝,包括它們的依賴項,這樣你可以確保專案在生產環境中運行的狀態與開發時在你的電腦上運行的狀態完全相同,這被稱為**鎖定**
+* 還有很多其他功能
+
+## 結論
+
+如果你讀過並理解了所有這些,現在**你對虛擬環境的了解已超過許多開發者**。🤓
+
+未來當你為看起來複雜的問題除錯時,了解這些細節很可能會有所幫助,你會知道**它是如何在底層運作的**。😎
diff --git a/docs/zh-hant/mkdocs.yml b/docs/zh-hant/mkdocs.yml
new file mode 100644
index 000000000..de18856f4
--- /dev/null
+++ b/docs/zh-hant/mkdocs.yml
@@ -0,0 +1 @@
+INHERIT: ../en/mkdocs.yml
diff --git a/docs/zh/docs/advanced/additional-responses.md b/docs/zh/docs/advanced/additional-responses.md
new file mode 100644
index 000000000..362ef9460
--- /dev/null
+++ b/docs/zh/docs/advanced/additional-responses.md
@@ -0,0 +1,221 @@
+# OPENAPI 中的其他响应
+
+您可以声明附加响应,包括附加状态代码、媒体类型、描述等。
+
+这些额外的响应将包含在OpenAPI模式中,因此它们也将出现在API文档中。
+
+但是对于那些额外的响应,你必须确保你直接返回一个像 `JSONResponse` 一样的 `Response` ,并包含你的状态代码和内容。
+
+## `model`附加响应
+您可以向路径操作装饰器传递参数 `responses` 。
+
+它接收一个 `dict`,键是每个响应的状态代码(如`200`),值是包含每个响应信息的其他 `dict`。
+
+每个响应字典都可以有一个关键模型,其中包含一个 `Pydantic` 模型,就像 `response_model` 一样。
+
+**FastAPI**将采用该模型,生成其`JSON Schema`并将其包含在`OpenAPI`中的正确位置。
+
+例如,要声明另一个具有状态码 `404` 和`Pydantic`模型 `Message` 的响应,可以写:
+{* ../../docs_src/additional_responses/tutorial001.py hl[18,22] *}
+
+/// note
+
+请记住,您必须直接返回 `JSONResponse` 。
+
+///
+
+/// info
+
+`model` 密钥不是OpenAPI的一部分。
+**FastAPI**将从那里获取`Pydantic`模型,生成` JSON Schema` ,并将其放在正确的位置。
+- 正确的位置是:
+ - 在键 `content` 中,其具有另一个`JSON`对象( `dict` )作为值,该`JSON`对象包含:
+ - 媒体类型的密钥,例如 `application/json` ,它包含另一个`JSON`对象作为值,该对象包含:
+ - 一个键` schema` ,它的值是来自模型的`JSON Schema`,正确的位置在这里。
+ - **FastAPI**在这里添加了对OpenAPI中另一个地方的全局JSON模式的引用,而不是直接包含它。这样,其他应用程序和客户端可以直接使用这些JSON模式,提供更好的代码生成工具等。
+
+///
+
+**在OpenAPI中为该路径操作生成的响应将是:**
+
+```json hl_lines="3-12"
+{
+ "responses": {
+ "404": {
+ "description": "Additional Response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Message"
+ }
+ }
+ }
+ },
+ "200": {
+ "description": "Successful Response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Item"
+ }
+ }
+ }
+ },
+ "422": {
+ "description": "Validation Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/HTTPValidationError"
+ }
+ }
+ }
+ }
+ }
+}
+
+```
+**模式被引用到OpenAPI模式中的另一个位置:**
+```json hl_lines="4-16"
+{
+ "components": {
+ "schemas": {
+ "Message": {
+ "title": "Message",
+ "required": [
+ "message"
+ ],
+ "type": "object",
+ "properties": {
+ "message": {
+ "title": "Message",
+ "type": "string"
+ }
+ }
+ },
+ "Item": {
+ "title": "Item",
+ "required": [
+ "id",
+ "value"
+ ],
+ "type": "object",
+ "properties": {
+ "id": {
+ "title": "Id",
+ "type": "string"
+ },
+ "value": {
+ "title": "Value",
+ "type": "string"
+ }
+ }
+ },
+ "ValidationError": {
+ "title": "ValidationError",
+ "required": [
+ "loc",
+ "msg",
+ "type"
+ ],
+ "type": "object",
+ "properties": {
+ "loc": {
+ "title": "Location",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "msg": {
+ "title": "Message",
+ "type": "string"
+ },
+ "type": {
+ "title": "Error Type",
+ "type": "string"
+ }
+ }
+ },
+ "HTTPValidationError": {
+ "title": "HTTPValidationError",
+ "type": "object",
+ "properties": {
+ "detail": {
+ "title": "Detail",
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ValidationError"
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+```
+## 主响应的其他媒体类型
+
+您可以使用相同的 `responses` 参数为相同的主响应添加不同的媒体类型。
+
+例如,您可以添加一个额外的媒体类型` image/png` ,声明您的路径操作可以返回JSON对象(媒体类型 `application/json` )或PNG图像:
+
+{* ../../docs_src/additional_responses/tutorial002.py hl[19:24,28] *}
+
+/// note
+
+- 请注意,您必须直接使用 `FileResponse` 返回图像。
+
+///
+
+/// info
+
+- 除非在 `responses` 参数中明确指定不同的媒体类型,否则**FastAPI**将假定响应与主响应类具有相同的媒体类型(默认为` application/json` )。
+- 但是如果您指定了一个自定义响应类,并将 `None `作为其媒体类型,**FastAPI**将使用 `application/json` 作为具有关联模型的任何其他响应。
+
+///
+
+## 组合信息
+您还可以联合接收来自多个位置的响应信息,包括 `response_model `、 `status_code` 和 `responses `参数。
+
+您可以使用默认的状态码 `200` (或者您需要的自定义状态码)声明一个 `response_model `,然后直接在OpenAPI模式中在 `responses` 中声明相同响应的其他信息。
+
+**FastAPI**将保留来自 `responses` 的附加信息,并将其与模型中的JSON Schema结合起来。
+
+例如,您可以使用状态码 `404` 声明响应,该响应使用`Pydantic`模型并具有自定义的` description` 。
+
+以及一个状态码为 `200` 的响应,它使用您的 `response_model` ,但包含自定义的 `example` :
+
+{* ../../docs_src/additional_responses/tutorial003.py hl[20:31] *}
+
+所有这些都将被合并并包含在您的OpenAPI中,并在API文档中显示:
+
+## 联合预定义响应和自定义响应
+
+您可能希望有一些应用于许多路径操作的预定义响应,但是你想将不同的路径和自定义的相应组合在一块。
+对于这些情况,你可以使用Python的技术,将 `dict` 与 `**dict_to_unpack` 解包:
+```Python
+old_dict = {
+ "old key": "old value",
+ "second old key": "second old value",
+}
+new_dict = {**old_dict, "new key": "new value"}
+```
+
+这里, new_dict 将包含来自 old_dict 的所有键值对加上新的键值对:
+```python
+{
+ "old key": "old value",
+ "second old key": "second old value",
+ "new key": "new value",
+}
+```
+您可以使用该技术在路径操作中重用一些预定义的响应,并将它们与其他自定义响应相结合。
+**例如:**
+{* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *}
+## 有关OpenAPI响应的更多信息
+
+要了解您可以在响应中包含哪些内容,您可以查看OpenAPI规范中的以下部分:
+ + [OpenAPI响应对象](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responsesObject),它包括 Response Object 。
+ + [OpenAPI响应对象](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responseObject),您可以直接在 `responses` 参数中的每个响应中包含任何内容。包括 `description` 、 `headers` 、 `content` (其中是声明不同的媒体类型和JSON Schemas)和 `links` 。
diff --git a/docs/zh/docs/advanced/additional-status-codes.md b/docs/zh/docs/advanced/additional-status-codes.md
index 1cb724f1d..b048a2a17 100644
--- a/docs/zh/docs/advanced/additional-status-codes.md
+++ b/docs/zh/docs/advanced/additional-status-codes.md
@@ -14,21 +14,25 @@
要实现它,导入 `JSONResponse`,然后在其中直接返回你的内容,并将 `status_code` 设置为为你要的值。
-```Python hl_lines="2 19"
-{!../../../docs_src/additional_status_codes/tutorial001.py!}
-```
+{* ../../docs_src/additional_status_codes/tutorial001.py hl[4,25] *}
-!!! warning "警告"
- 当你直接返回一个像上面例子中的 `Response` 对象时,它会直接返回。
+/// warning | 警告
- FastAPI 不会用模型等对该响应进行序列化。
-
- 确保其中有你想要的数据,且返回的值为合法的 JSON(如果你使用 `JSONResponse` 的话)。
+当你直接返回一个像上面例子中的 `Response` 对象时,它会直接返回。
-!!! note "技术细节"
- 你也可以使用 `from starlette.responses import JSONResponse`。
+FastAPI 不会用模型等对该响应进行序列化。
- 出于方便,**FastAPI** 为开发者提供同 `starlette.responses` 一样的 `fastapi.responses`。但是大多数可用的响应都是直接来自 Starlette。`status` 也是一样。
+确保其中有你想要的数据,且返回的值为合法的 JSON(如果你使用 `JSONResponse` 的话)。
+
+///
+
+/// note | 技术细节
+
+你也可以使用 `from starlette.responses import JSONResponse`。
+
+出于方便,**FastAPI** 为开发者提供同 `starlette.responses` 一样的 `fastapi.responses`。但是大多数可用的响应都是直接来自 Starlette。`status` 也是一样。
+
+///
## OpenAPI 和 API 文档
diff --git a/docs/zh/docs/advanced/advanced-dependencies.md b/docs/zh/docs/advanced/advanced-dependencies.md
new file mode 100644
index 000000000..8375bd48e
--- /dev/null
+++ b/docs/zh/docs/advanced/advanced-dependencies.md
@@ -0,0 +1,65 @@
+# 高级依赖项
+
+## 参数化的依赖项
+
+我们之前看到的所有依赖项都是写死的函数或类。
+
+但也可以为依赖项设置参数,避免声明多个不同的函数或类。
+
+假设要创建校验查询参数 `q` 是否包含固定内容的依赖项。
+
+但此处要把待检验的固定内容定义为参数。
+
+## **可调用**实例
+
+Python 可以把类实例变为**可调用项**。
+
+这里说的不是类本身(类本就是可调用项),而是类实例。
+
+为此,需要声明 `__call__` 方法:
+
+{* ../../docs_src/dependencies/tutorial011.py hl[10] *}
+
+本例中,**FastAPI** 使用 `__call__` 检查附加参数及子依赖项,稍后,还要调用它向*路径操作函数*传递值。
+
+## 参数化实例
+
+接下来,使用 `__init__` 声明用于**参数化**依赖项的实例参数:
+
+{* ../../docs_src/dependencies/tutorial011.py hl[7] *}
+
+本例中,**FastAPI** 不使用 `__init__`,我们要直接在代码中使用。
+
+## 创建实例
+
+使用以下代码创建类实例:
+
+{* ../../docs_src/dependencies/tutorial011.py hl[16] *}
+
+这样就可以**参数化**依赖项,它包含 `checker.fixed_content` 的属性 - `"bar"`。
+
+## 把实例作为依赖项
+
+然后,不要再在 `Depends(checker)` 中使用 `Depends(FixedContentQueryChecker)`, 而是要使用 `checker`,因为依赖项是类实例 - `checker`,不是类。
+
+处理依赖项时,**FastAPI** 以如下方式调用 `checker`:
+
+```Python
+checker(q="somequery")
+```
+
+……并用*路径操作函数*的参数 `fixed_content_included` 返回依赖项的值:
+
+{* ../../docs_src/dependencies/tutorial011.py hl[20] *}
+
+/// tip | 提示
+
+本章示例有些刻意,也看不出有什么用处。
+
+这个简例只是为了说明高级依赖项的运作机制。
+
+在有关安全的章节中,工具函数将以这种方式实现。
+
+只要能理解本章内容,就能理解安全工具背后的运行机制。
+
+///
diff --git a/docs/zh/docs/advanced/async-tests.md b/docs/zh/docs/advanced/async-tests.md
new file mode 100644
index 000000000..b5ac15b5b
--- /dev/null
+++ b/docs/zh/docs/advanced/async-tests.md
@@ -0,0 +1,99 @@
+# 异步测试
+
+您已经了解了如何使用 `TestClient` 测试 **FastAPI** 应用程序。但是到目前为止,您只了解了如何编写同步测试,而没有使用 `async` 异步函数。
+
+在测试中能够使用异步函数可能会很有用,比如当您需要异步查询数据库的时候。想象一下,您想要测试向 FastAPI 应用程序发送请求,然后验证您的后端是否成功在数据库中写入了正确的数据,与此同时您使用了异步的数据库的库。
+
+让我们看看如何才能实现这一点。
+
+## pytest.mark.anyio
+
+如果我们想在测试中调用异步函数,那么我们的测试函数必须是异步的。 AnyIO 为此提供了一个简洁的插件,它允许我们指定一些测试函数要异步调用。
+
+## HTTPX
+
+即使您的 **FastAPI** 应用程序使用普通的 `def` 函数而不是 `async def` ,它本质上仍是一个 `async` 异步应用程序。
+
+`TestClient` 在内部通过一些“魔法”操作,使得您可以在普通的 `def` 测试函数中调用异步的 FastAPI 应用程序,并使用标准的 pytest。但当我们在异步函数中使用它时,这种“魔法”就不再生效了。由于测试以异步方式运行,我们无法在测试函数中继续使用 `TestClient`。
+
+`TestClient` 是基于
HTTPX 的。幸运的是,我们可以直接使用它来测试API。
+
+## 示例
+
+举个简单的例子,让我们来看一个[更大的应用](../tutorial/bigger-applications.md){.internal-link target=_blank}和[测试](../tutorial/testing.md){.internal-link target=_blank}中描述的类似文件结构:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+│ └── test_main.py
+```
+
+文件 `main.py` 将包含:
+
+{* ../../docs_src/async_tests/main.py *}
+
+文件 `test_main.py` 将包含针对 `main.py` 的测试,现在它可能看起来如下:
+
+{* ../../docs_src/async_tests/test_main.py *}
+
+## 运行测试
+
+您可以通过以下方式照常运行测试:
+
+
+
+```console
+$ pytest
+
+---> 100%
+```
+
+
+
+## 详细说明
+
+这个标记 `@pytest.mark.anyio` 会告诉 pytest 该测试函数应该被异步调用:
+
+{* ../../docs_src/async_tests/test_main.py hl[7] *}
+
+/// tip
+
+请注意,测试函数现在用的是 `async def`,而不是像以前使用 `TestClient` 时那样只是 `def` 。
+
+///
+
+我们现在可以使用应用程序创建一个 `AsyncClient` ,并使用 `await` 向其发送异步请求。
+
+{* ../../docs_src/async_tests/test_main.py hl[9:12] *}
+
+这相当于:
+
+```Python
+response = client.get('/')
+```
+
+我们曾经通过它向 `TestClient` 发出请求。
+
+/// tip
+
+请注意,我们正在将 async/await 与新的 `AsyncClient` 一起使用——请求是异步的。
+
+///
+
+/// warning
+
+如果您的应用程序依赖于生命周期事件, `AsyncClient` 将不会触发这些事件。为了确保它们被触发,请使用
florimondmanca/asgi-lifespan 中的 `LifespanManager` 。
+
+///
+
+## 其他异步函数调用
+
+由于测试函数现在是异步的,因此除了在测试中向 FastAPI 应用程序发送请求之外,您现在还可以调用(和使用 `await` 等待)其他 `async` 异步函数,就和您在代码中的其他任何地方调用它们的方法一样。
+
+/// tip
+
+如果您在测试程序中集成异步函数调用的时候遇到一个 `RuntimeError: Task attached to a different loop` 的报错(例如,使用
MongoDB 的 MotorClient 时),请记住,只能在异步函数中实例化需要事件循环的对象,例如通过 `'@app.on_event("startup")` 回调函数进行初始化。
+
+///
diff --git a/docs/zh/docs/advanced/behind-a-proxy.md b/docs/zh/docs/advanced/behind-a-proxy.md
new file mode 100644
index 000000000..f8f61c8a3
--- /dev/null
+++ b/docs/zh/docs/advanced/behind-a-proxy.md
@@ -0,0 +1,357 @@
+# 使用代理
+
+有些情况下,您可能要使用 Traefik 或 Nginx 等**代理**服务器,并添加应用不能识别的附加路径前缀配置。
+
+此时,要使用 `root_path` 配置应用。
+
+`root_path` 是 ASGI 规范提供的机制,FastAPI 就是基于此规范开发的(通过 Starlette)。
+
+`root_path` 用于处理这些特定情况。
+
+在挂载子应用时,也可以在内部使用。
+
+## 移除路径前缀的代理
+
+本例中,移除路径前缀的代理是指在代码中声明路径 `/app`,然后在应用顶层添加代理,把 **FastAPI** 应用放在 `/api/v1` 路径下。
+
+本例的原始路径 `/app` 实际上是在 `/api/v1/app` 提供服务。
+
+哪怕所有代码都假设只有 `/app`。
+
+代理只在把请求传送给 Uvicorn 之前才会**移除路径前缀**,让应用以为它是在 `/app` 提供服务,因此不必在代码中加入前缀 `/api/v1`。
+
+但之后,在(前端)打开 API 文档时,代理会要求在 `/openapi.json`,而不是 `/api/v1/openapi.json` 中提取 OpenAPI 概图。
+
+因此, (运行在浏览器中的)前端会尝试访问 `/openapi.json`,但没有办法获取 OpenAPI 概图。
+
+这是因为应用使用了以 `/api/v1` 为路径前缀的代理,前端要从 `/api/v1/openapi.json` 中提取 OpenAPI 概图。
+
+```mermaid
+graph LR
+
+browser("Browser")
+proxy["Proxy on http://0.0.0.0:9999/api/v1/app"]
+server["Server on http://127.0.0.1:8000/app"]
+
+browser --> proxy
+proxy --> server
+```
+
+/// tip | 提示
+
+IP `0.0.0.0` 常用于指程序监听本机或服务器上的所有有效 IP。
+
+///
+
+API 文档还需要 OpenAPI 概图声明 API `server` 位于 `/api/v1`(使用代理时的 URL)。例如:
+
+```JSON hl_lines="4-8"
+{
+ "openapi": "3.0.2",
+ // More stuff here
+ "servers": [
+ {
+ "url": "/api/v1"
+ }
+ ],
+ "paths": {
+ // More stuff here
+ }
+}
+```
+
+本例中的 `Proxy` 是 **Traefik**,`server` 是运行 FastAPI 应用的 **Uvicorn**。
+
+### 提供 `root_path`
+
+为此,要以如下方式使用命令行选项 `--root-path`:
+
+
+
+```console
+$ uvicorn main:app --root-path /api/v1
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+
+
+Hypercorn 也支持 `--root-path `选项。
+
+/// note | 技术细节
+
+ASGI 规范定义的 `root_path` 就是为了这种用例。
+
+并且 `--root-path` 命令行选项支持 `root_path`。
+
+///
+
+### 查看当前的 `root_path`
+
+获取应用为每个请求使用的当前 `root_path`,这是 `scope` 字典的内容(也是 ASGI 规范的内容)。
+
+我们在这里的信息里包含 `roo_path` 只是为了演示。
+
+{* ../../docs_src/behind_a_proxy/tutorial001.py hl[8] *}
+
+然后,用以下命令启动 Uvicorn:
+
+
+
+```console
+$ uvicorn main:app --root-path /api/v1
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+
+
+返回的响应如下:
+
+```JSON
+{
+ "message": "Hello World",
+ "root_path": "/api/v1"
+}
+```
+
+### 在 FastAPI 应用里设置 `root_path`
+
+还有一种方案,如果不能提供 `--root-path` 或等效的命令行选项,则在创建 FastAPI 应用时要设置 `root_path` 参数。
+
+{* ../../docs_src/behind_a_proxy/tutorial002.py hl[3] *}
+
+传递 `root_path` 给 `FastAPI` 与传递 `--root-path` 命令行选项给 Uvicorn 或 Hypercorn 一样。
+
+### 关于 `root_path`
+
+注意,服务器(Uvicorn)只是把 `root_path` 传递给应用。
+
+在浏览器中输入
http://127.0.0.1:8000/app 时能看到标准响应:
+
+```JSON
+{
+ "message": "Hello World",
+ "root_path": "/api/v1"
+}
+```
+
+它不要求访问 `http://127.0.0.1:800/api/v1/app`。
+
+Uvicorn 预期代理在 `http://127.0.0.1:8000/app` 访问 Uvicorn,而在顶部添加 `/api/v1` 前缀是代理要做的事情。
+
+## 关于移除路径前缀的代理
+
+注意,移除路径前缀的代理只是配置代理的方式之一。
+
+大部分情况下,代理默认都不会移除路径前缀。
+
+(未移除路径前缀时)代理监听 `https://myawesomeapp.com` 等对象,如果浏览器跳转到 `https://myawesomeapp.com/api/v1/app`,且服务器(例如 Uvicorn)监听 `http://127.0.0.1:8000` 代理(未移除路径前缀) 会在同样的路径:`http://127.0.0.1:8000/api/v1/app` 访问 Uvicorn。
+
+## 本地测试 Traefik
+
+您可以轻易地在本地使用
Traefik 运行移除路径前缀的试验。
+
+
下载 Traefik,这是一个二进制文件,需要解压文件,并在 Terminal 中直接运行。
+
+然后创建包含如下内容的 `traefik.toml` 文件:
+
+```TOML hl_lines="3"
+[entryPoints]
+ [entryPoints.http]
+ address = ":9999"
+
+[providers]
+ [providers.file]
+ filename = "routes.toml"
+```
+
+这个文件把 Traefik 监听端口设置为 `9999`,并设置要使用另一个文件 `routes.toml`。
+
+/// tip | 提示
+
+使用端口 9999 代替标准的 HTTP 端口 80,这样就不必使用管理员权限运行(`sudo`)。
+
+///
+
+接下来,创建 `routes.toml`:
+
+```TOML hl_lines="5 12 20"
+[http]
+ [http.middlewares]
+
+ [http.middlewares.api-stripprefix.stripPrefix]
+ prefixes = ["/api/v1"]
+
+ [http.routers]
+
+ [http.routers.app-http]
+ entryPoints = ["http"]
+ service = "app"
+ rule = "PathPrefix(`/api/v1`)"
+ middlewares = ["api-stripprefix"]
+
+ [http.services]
+
+ [http.services.app]
+ [http.services.app.loadBalancer]
+ [[http.services.app.loadBalancer.servers]]
+ url = "http://127.0.0.1:8000"
+```
+
+这个文件配置 Traefik 使用路径前缀 `/api/v1`。
+
+然后,它把请求重定位到运行在 `http://127.0.0.1:8000` 上的 Uvicorn。
+
+现在,启动 Traefik:
+
+
+
+```console
+$ ./traefik --configFile=traefik.toml
+
+INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml
+```
+
+
+
+接下来,使用 Uvicorn 启动应用,并使用 `--root-path` 选项:
+
+
+
+```console
+$ uvicorn main:app --root-path /api/v1
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+
+
+### 查看响应
+
+访问含 Uvicorn 端口的 URL:
http://127.0.0.1:8000/app,就能看到标准响应:
+
+```JSON
+{
+ "message": "Hello World",
+ "root_path": "/api/v1"
+}
+```
+
+/// tip | 提示
+
+注意,就算访问 `http://127.0.0.1:8000/app`,也显示从选项 `--root-path` 中提取的 `/api/v1`,这是 `root_path` 的值。
+
+///
+
+打开含 Traefik 端口的 URL,包含路径前缀:
http://127.0.0.1:9999/api/v1/app。
+
+得到同样的响应:
+
+```JSON
+{
+ "message": "Hello World",
+ "root_path": "/api/v1"
+}
+```
+
+但这一次 URL 包含了代理提供的路径前缀:`/api/v1`。
+
+当然,这是通过代理访问应用的方式,因此,路径前缀 `/app/v1` 版本才是**正确**的。
+
+而不带路径前缀的版本(`http://127.0.0.1:8000/app`),则由 Uvicorn 直接提供,专供*代理*(Traefik)访问。
+
+这演示了代理(Traefik)如何使用路径前缀,以及服务器(Uvicorn)如何使用选项 `--root-path` 中的 `root_path`。
+
+### 查看文档
+
+但这才是有趣的地方 ✨
+
+访问应用的**官方**方式是通过含路径前缀的代理。因此,不出所料,如果没有在 URL 中添加路径前缀,直接访问通过 Uvicorn 运行的 API 文档,不能正常访问,因为需要通过代理才能访问。
+
+输入
http://127.0.0.1:8000/docs 查看 API 文档:
+
+

+
+但输入**官方**链接 `/api/v1/docs`,并使用端口 `9999` 访问 API 文档,就能正常运行了!🎉
+
+输入
http://127.0.0.1:9999/api/v1/docs 查看文档:
+
+

+
+一切正常。 ✔️
+
+这是因为 FastAPI 在 OpenAPI 里使用 `root_path` 提供的 URL 创建默认 `server`。
+
+## 附加的服务器
+
+/// warning | 警告
+
+此用例较难,可以跳过。
+
+///
+
+默认情况下,**FastAPI** 使用 `root_path` 的链接在 OpenAPI 概图中创建 `server`。
+
+但也可以使用其它备选 `servers`,例如,需要同一个 API 文档与 staging 和生产环境交互。
+
+如果传递自定义 `servers` 列表,并有 `root_path`( 因为 API 使用了代理),**FastAPI** 会在列表开头使用这个 `root_path` 插入**服务器**。
+
+例如:
+
+{* ../../docs_src/behind_a_proxy/tutorial003.py hl[4:7] *}
+
+这段代码生产如下 OpenAPI 概图:
+
+```JSON hl_lines="5-7"
+{
+ "openapi": "3.0.2",
+ // More stuff here
+ "servers": [
+ {
+ "url": "/api/v1"
+ },
+ {
+ "url": "https://stag.example.com",
+ "description": "Staging environment"
+ },
+ {
+ "url": "https://prod.example.com",
+ "description": "Production environment"
+ }
+ ],
+ "paths": {
+ // More stuff here
+ }
+}
+```
+
+/// tip | 提示
+
+注意,自动生成服务器时,`url` 的值 `/api/v1` 提取自 `roog_path`。
+
+///
+
+
http://127.0.0.1:9999/api/v1/docs 的 API 文档所示如下:
+
+

+
+/// tip | 提示
+
+API 文档与所选的服务器进行交互。
+
+///
+
+### 从 `root_path` 禁用自动服务器
+
+如果不想让 **FastAPI** 包含使用 `root_path` 的自动服务器,则要使用参数 `root_path_in_servers=False`:
+
+{* ../../docs_src/behind_a_proxy/tutorial004.py hl[9] *}
+
+这样,就不会在 OpenAPI 概图中包含服务器了。
+
+## 挂载子应用
+
+如需挂载子应用(详见 [子应用 - 挂载](sub-applications.md){.internal-link target=_blank}),也要通过 `root_path` 使用代理,这与正常应用一样,别无二致。
+
+FastAPI 在内部使用 `root_path`,因此子应用也可以正常运行。✨
diff --git a/docs/zh/docs/advanced/custom-response.md b/docs/zh/docs/advanced/custom-response.md
index 5f1a74e9e..22a9b4b51 100644
--- a/docs/zh/docs/advanced/custom-response.md
+++ b/docs/zh/docs/advanced/custom-response.md
@@ -12,8 +12,11 @@
并且如果该 `Response` 有一个 JSON 媒体类型(`application/json`),比如使用 `JSONResponse` 或者 `UJSONResponse` 的时候,返回的数据将使用你在路径操作装饰器中声明的任何 Pydantic 的 `response_model` 自动转换(和过滤)。
-!!! note "说明"
- 如果你使用不带有任何媒体类型的响应类,FastAPI 认为你的响应没有任何内容,所以不会在生成的OpenAPI文档中记录响应格式。
+/// note | 说明
+
+如果你使用不带有任何媒体类型的响应类,FastAPI 认为你的响应没有任何内容,所以不会在生成的OpenAPI文档中记录响应格式。
+
+///
## 使用 `ORJSONResponse`
@@ -21,21 +24,23 @@
导入你想要使用的 `Response` 类(子类)然后在 *路径操作装饰器* 中声明它。
-```Python hl_lines="2 7"
-{!../../../docs_src/custom_response/tutorial001b.py!}
-```
+{* ../../docs_src/custom_response/tutorial001b.py hl[2,7] *}
+
+/// info | 提示
-!!! info "提示"
- 参数 `response_class` 也会用来定义响应的「媒体类型」。
+参数 `response_class` 也会用来定义响应的「媒体类型」。
- 在这个例子中,HTTP 头的 `Content-Type` 会被设置成 `application/json`。
+在这个例子中,HTTP 头的 `Content-Type` 会被设置成 `application/json`。
- 并且在 OpenAPI 文档中也会这样记录。
+并且在 OpenAPI 文档中也会这样记录。
-!!! tip "小贴士"
- `ORJSONResponse` 目前只在 FastAPI 中可用,而在 Starlette 中不可用。
+///
+/// tip | 小贴士
+`ORJSONResponse` 目前只在 FastAPI 中可用,而在 Starlette 中不可用。
+
+///
## HTML 响应
@@ -44,32 +49,37 @@
* 导入 `HTMLResponse`。
* 将 `HTMLResponse` 作为你的 *路径操作* 的 `response_class` 参数传入。
-```Python hl_lines="2 7"
-{!../../../docs_src/custom_response/tutorial002.py!}
-```
+{* ../../docs_src/custom_response/tutorial002.py hl[2,7] *}
+
+/// info | 提示
-!!! info "提示"
- 参数 `response_class` 也会用来定义响应的「媒体类型」。
+参数 `response_class` 也会用来定义响应的「媒体类型」。
- 在这个例子中,HTTP 头的 `Content-Type` 会被设置成 `text/html`。
+在这个例子中,HTTP 头的 `Content-Type` 会被设置成 `text/html`。
- 并且在 OpenAPI 文档中也会这样记录。
+并且在 OpenAPI 文档中也会这样记录。
+
+///
### 返回一个 `Response`
正如你在 [直接返回响应](response-directly.md){.internal-link target=_blank} 中了解到的,你也可以通过直接返回响应在 *路径操作* 中直接重载响应。
和上面一样的例子,返回一个 `HTMLResponse` 看起来可能是这样:
-
-```Python hl_lines="2 7 19"
-{!../../../docs_src/custom_response/tutorial003.py!}
-```
-!!! warning "警告"
- *路径操作函数* 直接返回的 `Response` 不会被 OpenAPI 的文档记录(比如,`Content-Type` 不会被文档记录),并且在自动化交互文档中也是不可见的。
+{* ../../docs_src/custom_response/tutorial003.py hl[2,7,19] *}
+
+/// warning | 警告
+
+*路径操作函数* 直接返回的 `Response` 不会被 OpenAPI 的文档记录(比如,`Content-Type` 不会被文档记录),并且在自动化交互文档中也是不可见的。
+
+///
+
+/// info | 提示
-!!! info "提示"
- 当然,实际的 `Content-Type` 头,状态码等等,将来自于你返回的 `Response` 对象。
+当然,实际的 `Content-Type` 头,状态码等等,将来自于你返回的 `Response` 对象。
+
+///
### OpenAPI 中的文档和重载 `Response`
@@ -81,9 +91,7 @@
比如像这样:
-```Python hl_lines="7 23 21"
-{!../../../docs_src/custom_response/tutorial004.py!}
-```
+{* ../../docs_src/custom_response/tutorial004.py hl[7,23,21] *}
在这个例子中,函数 `generate_html_response()` 已经生成并返回 `Response` 对象而不是在 `str` 中返回 HTML。
@@ -99,10 +107,13 @@
要记得你可以使用 `Response` 来返回任何其他东西,甚至创建一个自定义的子类。
-!!! note "技术细节"
- 你也可以使用 `from starlette.responses import HTMLResponse`。
+/// note | 技术细节
+
+你也可以使用 `from starlette.responses import HTMLResponse`。
+
+**FastAPI** 提供了同 `fastapi.responses` 相同的 `starlette.responses` 只是为了方便开发者。但大多数可用的响应都直接来自 Starlette。
- **FastAPI** 提供了同 `fastapi.responses` 相同的 `starlette.responses` 只是为了方便开发者。但大多数可用的响应都直接来自 Starlette。
+///
### `Response`
@@ -120,9 +131,7 @@
FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它还将包含一个基于 media_type 的 Content-Type 头,并为文本类型附加一个字符集。
-```Python hl_lines="1 18"
-{!../../../docs_src/response_directly/tutorial002.py!}
-```
+{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
### `HTMLResponse`
@@ -132,9 +141,7 @@ FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它
接受文本或字节并返回纯文本响应。
-```Python hl_lines="2 7 9"
-{!../../../docs_src/custom_response/tutorial005.py!}
-```
+{* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *}
### `JSONResponse`
@@ -151,31 +158,31 @@ FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它
`UJSONResponse` 是一个使用
`ujson` 的可选 JSON 响应。
-!!! warning "警告"
- 在处理某些边缘情况时,`ujson` 不如 Python 的内置实现那么谨慎。
+/// warning | 警告
+
+在处理某些边缘情况时,`ujson` 不如 Python 的内置实现那么谨慎。
+
+///
-```Python hl_lines="2 7"
-{!../../../docs_src/custom_response/tutorial001.py!}
-```
+{* ../../docs_src/custom_response/tutorial001.py hl[2,7] *}
-!!! tip "小贴士"
- `ORJSONResponse` 可能是一个更快的选择。
+/// tip | 小贴士
+
+`ORJSONResponse` 可能是一个更快的选择。
+
+///
### `RedirectResponse`
返回 HTTP 重定向。默认情况下使用 307 状态代码(临时重定向)。
-```Python hl_lines="2 9"
-{!../../../docs_src/custom_response/tutorial006.py!}
-```
+{* ../../docs_src/custom_response/tutorial006.py hl[2,9] *}
### `StreamingResponse`
采用异步生成器或普通生成器/迭代器,然后流式传输响应主体。
-```Python hl_lines="2 14"
-{!../../../docs_src/custom_response/tutorial007.py!}
-```
+{* ../../docs_src/custom_response/tutorial007.py hl[2,14] *}
#### 对类似文件的对象使用 `StreamingResponse`
@@ -183,12 +190,13 @@ FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它
包括许多与云存储,视频处理等交互的库。
-```Python hl_lines="2 10-12 14"
-{!../../../docs_src/custom_response/tutorial008.py!}
-```
+{* ../../docs_src/custom_response/tutorial008.py hl[2,10:12,14] *}
+
+/// tip | 小贴士
+
+注意在这里,因为我们使用的是不支持 `async` 和 `await` 的标准 `open()`,我们使用普通的 `def` 声明了路径操作。
-!!! tip "小贴士"
- 注意在这里,因为我们使用的是不支持 `async` 和 `await` 的标准 `open()`,我们使用普通的 `def` 声明了路径操作。
+///
### `FileResponse`
@@ -203,9 +211,7 @@ FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它
文件响应将包含适当的 `Content-Length`,`Last-Modified` 和 `ETag` 的响应头。
-```Python hl_lines="2 10"
-{!../../../docs_src/custom_response/tutorial009.py!}
-```
+{* ../../docs_src/custom_response/tutorial009.py hl[2,10] *}
## 额外文档
diff --git a/docs/zh/docs/advanced/dataclasses.md b/docs/zh/docs/advanced/dataclasses.md
new file mode 100644
index 000000000..c74ce65c3
--- /dev/null
+++ b/docs/zh/docs/advanced/dataclasses.md
@@ -0,0 +1,97 @@
+# 使用数据类
+
+FastAPI 基于 **Pydantic** 构建,前文已经介绍过如何使用 Pydantic 模型声明请求与响应。
+
+但 FastAPI 还可以使用数据类(
`dataclasses`):
+
+{* ../../docs_src/dataclasses/tutorial001.py hl[1,7:12,19:20] *}
+
+这还是借助于 **Pydantic** 及其
内置的 `dataclasses`。
+
+因此,即便上述代码没有显式使用 Pydantic,FastAPI 仍会使用 Pydantic 把标准数据类转换为 Pydantic 数据类(`dataclasses`)。
+
+并且,它仍然支持以下功能:
+
+* 数据验证
+* 数据序列化
+* 数据存档等
+
+数据类的和运作方式与 Pydantic 模型相同。实际上,它的底层使用的也是 Pydantic。
+
+/// info | 说明
+
+注意,数据类不支持 Pydantic 模型的所有功能。
+
+因此,开发时仍需要使用 Pydantic 模型。
+
+但如果数据类很多,这一技巧能给 FastAPI 开发 Web API 增添不少助力。🤓
+
+///
+
+## `response_model` 使用数据类
+
+在 `response_model` 参数中使用 `dataclasses`:
+
+{* ../../docs_src/dataclasses/tutorial002.py hl[1,7:13,19] *}
+
+本例把数据类自动转换为 Pydantic 数据类。
+
+API 文档中也会显示相关概图:
+
+

+
+## 在嵌套数据结构中使用数据类
+
+您还可以把 `dataclasses` 与其它类型注解组合在一起,创建嵌套数据结构。
+
+还有一些情况也可以使用 Pydantic 的 `dataclasses`。例如,在 API 文档中显示错误。
+
+本例把标准的 `dataclasses` 直接替换为 `pydantic.dataclasses`:
+
+```{ .python .annotate hl_lines="1 5 8-11 14-17 23-25 28" }
+{!../../docs_src/dataclasses/tutorial003.py!}
+```
+
+1. 本例依然要从标准的 `dataclasses` 中导入 `field`;
+
+2. 使用 `pydantic.dataclasses` 直接替换 `dataclasses`;
+
+3. `Author` 数据类包含 `Item` 数据类列表;
+
+4. `Author` 数据类用于 `response_model` 参数;
+
+5. 其它带有数据类的标准类型注解也可以作为请求体;
+
+ 本例使用的是 `Item` 数据类列表;
+
+6. 这行代码返回的是包含 `items` 的字典,`items` 是数据类列表;
+
+ FastAPI 仍能把数据
序列化为 JSON;
+
+7. 这行代码中,`response_model` 的类型注解是 `Author` 数据类列表;
+
+ 再一次,可以把 `dataclasses` 与标准类型注解一起使用;
+
+8. 注意,*路径操作函数*使用的是普通函数,不是异步函数;
+
+ 与往常一样,在 FastAPI 中,可以按需组合普通函数与异步函数;
+
+ 如果不清楚何时使用异步函数或普通函数,请参阅**急不可待?**一节中对
`async` 与 `await` 的说明;
+
+9. *路径操作函数*返回的不是数据类(虽然它可以返回数据类),而是返回内含数据的字典列表;
+
+ FastAPI 使用(包含数据类的) `response_model` 参数转换响应。
+
+把 `dataclasses` 与其它类型注解组合在一起,可以组成不同形式的复杂数据结构。
+
+更多内容详见上述代码内的注释。
+
+## 深入学习
+
+您还可以把 `dataclasses` 与其它 Pydantic 模型组合在一起,继承合并的模型,把它们包含在您自己的模型里。
+
+详见
Pydantic 官档 - 数据类。
+
+## 版本
+
+本章内容自 FastAPI `0.67.0` 版起生效。🔖
diff --git a/docs/zh/docs/advanced/events.md b/docs/zh/docs/advanced/events.md
new file mode 100644
index 000000000..5ade0f0ff
--- /dev/null
+++ b/docs/zh/docs/advanced/events.md
@@ -0,0 +1,173 @@
+# 生命周期事件
+
+你可以定义在应用**启动**前执行的逻辑(代码)。这意味着在应用**开始接收请求**之前,这些代码只会被执行**一次**。
+
+同样地,你可以定义在应用**关闭**时应执行的逻辑。在这种情况下,这段代码将在**处理可能的多次请求后**执行**一次**。
+
+因为这段代码在应用开始接收请求**之前**执行,也会在处理可能的若干请求**之后**执行,它覆盖了整个应用程序的**生命周期**("生命周期"这个词很重要😉)。
+
+这对于设置你需要在整个应用中使用的**资源**非常有用,这些资源在请求之间**共享**,你可能需要在之后进行**释放**。例如,数据库连接池,或加载一个共享的机器学习模型。
+
+## 用例
+
+让我们从一个示例用例开始,看看如何解决它。
+
+假设你有几个**机器学习的模型**,你想要用它们来处理请求。
+
+相同的模型在请求之间是共享的,因此并非每个请求或每个用户各自拥有一个模型。
+
+假设加载模型可能**需要相当长的时间**,因为它必须从**磁盘**读取大量数据。因此你不希望每个请求都加载它。
+
+你可以在模块/文件的顶部加载它,但这也意味着即使你只是在运行一个简单的自动化测试,它也会**加载模型**,这样测试将**变慢**,因为它必须在能够独立运行代码的其他部分之前等待模型加载完成。
+
+这就是我们要解决的问题——在处理请求前加载模型,但只是在应用开始接收请求前,而不是代码执行时。
+
+## 生命周期 lifespan
+
+你可以使用`FastAPI()`应用的`lifespan`参数和一个上下文管理器(稍后我将为你展示)来定义**启动**和**关闭**的逻辑。
+
+让我们从一个例子开始,然后详细介绍。
+
+我们使用`yield`创建了一个异步函数`lifespan()`像这样:
+
+```Python hl_lines="16 19"
+{!../../docs_src/events/tutorial003.py!}
+```
+
+在这里,我们在 `yield` 之前将(虚拟的)模型函数放入机器学习模型的字典中,以此模拟加载模型的耗时**启动**操作。这段代码将在应用程序**开始处理请求之前**执行,即**启动**期间。
+
+然后,在 `yield` 之后,我们卸载模型。这段代码将会在应用程序**完成处理请求后**执行,即在**关闭**之前。这可以释放诸如内存或 GPU 之类的资源。
+
+/// tip | 提示
+
+**关闭**事件只会在你停止应用时触发。
+
+可能你需要启动一个新版本,或者你只是你厌倦了运行它。 🤷
+
+///
+
+## 生命周期函数
+
+首先要注意的是,我们定义了一个带有 `yield` 的异步函数。这与带有 `yield` 的依赖项非常相似。
+
+```Python hl_lines="14-19"
+{!../../docs_src/events/tutorial003.py!}
+```
+
+这个函数在 `yield`之前的部分,会在应用启动前执行。
+
+剩下的部分在 `yield` 之后,会在应用完成后执行。
+
+## 异步上下文管理器
+
+如你所见,这个函数有一个装饰器 `@asynccontextmanager` 。
+
+它将函数转化为所谓的“**异步上下文管理器**”。
+
+```Python hl_lines="1 13"
+{!../../docs_src/events/tutorial003.py!}
+```
+
+在 Python 中, **上下文管理器**是一个你可以在 `with` 语句中使用的东西,例如,`open()` 可以作为上下文管理器使用。
+
+```Python
+with open("file.txt") as file:
+ file.read()
+```
+
+Python 的最近几个版本也有了一个**异步上下文管理器**,你可以通过 `async with` 来使用:
+
+```Python
+async with lifespan(app):
+ await do_stuff()
+```
+
+你可以像上面一样创建了一个上下文管理器或者异步上下文管理器,它的作用是在进入 `with` 块时,执行 `yield` 之前的代码,并且在离开 `with` 块时,执行 `yield` 后面的代码。
+
+但在我们上面的例子里,我们并不是直接使用,而是传递给 FastAPI 来供其使用。
+
+`FastAPI()` 的 `lifespan` 参数接受一个**异步上下文管理器**,所以我们可以把我们新定义的上下文管理器 `lifespan` 传给它。
+
+```Python hl_lines="22"
+{!../../docs_src/events/tutorial003.py!}
+```
+
+## 替代事件(弃用)
+
+/// warning | 警告
+
+配置**启动**和**关闭**事件的推荐方法是使用 `FastAPI()` 应用的 `lifespan` 参数,如前所示。如果你提供了一个 `lifespan` 参数,启动(`startup`)和关闭(`shutdown`)事件处理器将不再生效。要么使用 `lifespan`,要么配置所有事件,两者不能共用。
+
+你可以跳过这一部分。
+
+///
+
+有一种替代方法可以定义在**启动**和**关闭**期间执行的逻辑。
+
+**FastAPI** 支持定义在应用启动前,或应用关闭时执行的事件处理器(函数)。
+
+事件函数既可以声明为异步函数(`async def`),也可以声明为普通函数(`def`)。
+
+### `startup` 事件
+
+使用 `startup` 事件声明 `app` 启动前运行的函数:
+
+{* ../../docs_src/events/tutorial001.py hl[8] *}
+
+本例中,`startup` 事件处理器函数为项目数据库(只是**字典**)提供了一些初始值。
+
+**FastAPI** 支持多个事件处理器函数。
+
+只有所有 `startup` 事件处理器运行完毕,**FastAPI** 应用才开始接收请求。
+
+### `shutdown` 事件
+
+使用 `shutdown` 事件声明 `app` 关闭时运行的函数:
+
+{* ../../docs_src/events/tutorial002.py hl[6] *}
+
+此处,`shutdown` 事件处理器函数在 `log.txt` 中写入一行文本 `Application shutdown`。
+
+/// info | 说明
+
+`open()` 函数中,`mode="a"` 指的是**追加**。因此这行文本会添加在文件已有内容之后,不会覆盖之前的内容。
+
+///
+
+/// tip | 提示
+
+注意,本例使用 Python `open()` 标准函数与文件交互。
+
+这个函数执行 I/O(输入/输出)操作,需要等待内容写进磁盘。
+
+但 `open()` 函数不支持使用 `async` 与 `await`。
+
+因此,声明事件处理函数要使用 `def`,不能使用 `asnyc def`。
+
+///
+
+### `startup` 和 `shutdown` 一起使用
+
+启动和关闭的逻辑很可能是连接在一起的,你可能希望启动某个东西然后结束它,获取一个资源然后释放它等等。
+
+在不共享逻辑或变量的不同函数中处理这些逻辑比较困难,因为你需要在全局变量中存储值或使用类似的方式。
+
+因此,推荐使用 `lifespan` 。
+
+## 技术细节
+
+只是为好奇者提供的技术细节。🤓
+
+在底层,这部分是
生命周期协议的一部分,参见 ASGI 技术规范,定义了称为启动(`startup`)和关闭(`shutdown`)的事件。
+
+/// info | 说明
+
+有关事件处理器的详情,请参阅
Starlette 官档 - 事件。
+
+包括如何处理生命周期状态,这可以用于程序的其他部分。
+
+///
+
+## 子应用
+
+🚨 **FastAPI** 只会触发主应用中的生命周期事件,不包括[子应用 - 挂载](sub-applications.md){.internal-link target=_blank}中的。
diff --git a/docs/zh/docs/advanced/generate-clients.md b/docs/zh/docs/advanced/generate-clients.md
new file mode 100644
index 000000000..bcb9ba2bf
--- /dev/null
+++ b/docs/zh/docs/advanced/generate-clients.md
@@ -0,0 +1,237 @@
+# 生成客户端
+
+因为 **FastAPI** 是基于OpenAPI规范的,自然您可以使用许多相匹配的工具,包括自动生成API文档 (由 Swagger UI 提供)。
+
+一个不太明显而又特别的优势是,你可以为你的API针对不同的**编程语言**来**生成客户端**(有时候被叫做
**SDKs** )。
+
+## OpenAPI 客户端生成
+
+有许多工具可以从**OpenAPI**生成客户端。
+
+一个常见的工具是
OpenAPI Generator。
+
+如果您正在开发**前端**,一个非常有趣的替代方案是
openapi-ts。
+
+## 生成一个 TypeScript 前端客户端
+
+让我们从一个简单的 FastAPI 应用开始:
+
+{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *}
+
+请注意,*路径操作* 定义了他们所用于请求数据和回应数据的模型,所使用的模型是`Item` 和 `ResponseMessage`。
+
+### API 文档
+
+如果您访问API文档,您将看到它具有在请求中发送和在响应中接收数据的**模式(schemas)**:
+
+

+
+您可以看到这些模式,因为它们是用程序中的模型声明的。
+
+那些信息可以在应用的 **OpenAPI模式** 被找到,然后显示在API文档中(通过Swagger UI)。
+
+OpenAPI中所包含的模型里有相同的信息可以用于 **生成客户端代码**。
+
+### 生成一个TypeScript 客户端
+
+现在我们有了带有模型的应用,我们可以为前端生成客户端代码。
+
+#### 安装 `openapi-ts`
+
+您可以使用以下工具在前端代码中安装 `openapi-ts`:
+
+
+
+```console
+$ npm install @hey-api/openapi-ts --save-dev
+
+---> 100%
+```
+
+
+
+#### 生成客户端代码
+
+要生成客户端代码,您可以使用现在将要安装的命令行应用程序 `openapi-ts`。
+
+因为它安装在本地项目中,所以您可能无法直接使用此命令,但您可以将其放在 `package.json` 文件中。
+
+它可能看起来是这样的:
+
+```JSON hl_lines="7"
+{
+ "name": "frontend-app",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "generate-client": "openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios"
+ },
+ "author": "",
+ "license": "",
+ "devDependencies": {
+ "@hey-api/openapi-ts": "^0.27.38",
+ "typescript": "^4.6.2"
+ }
+}
+```
+
+在这里添加 NPM `generate-client` 脚本后,您可以使用以下命令运行它:
+
+
+
+```console
+$ npm run generate-client
+
+frontend-app@1.0.0 generate-client /home/user/code/frontend-app
+> openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios
+```
+
+
+
+此命令将在 `./src/client` 中生成代码,并将在其内部使用 `axios`(前端HTTP库)。
+
+### 尝试客户端代码
+
+现在您可以导入并使用客户端代码,它可能看起来像这样,请注意,您可以为这些方法使用自动补全:
+
+

+
+您还将自动补全要发送的数据:
+
+

+
+/// tip
+
+请注意, `name` 和 `price` 的自动补全,是通过其在`Item`模型(FastAPI)中的定义实现的。
+
+///
+
+如果发送的数据字段不符,你也会看到编辑器的错误提示:
+
+

+
+响应(response)对象也拥有自动补全:
+
+

+
+## 带有标签的 FastAPI 应用
+
+在许多情况下,你的FastAPI应用程序会更复杂,你可能会使用标签来分隔不同组的*路径操作(path operations)*。
+
+例如,您可以有一个用 `items` 的部分和另一个用于 `users` 的部分,它们可以用标签来分隔:
+
+{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *}
+
+### 生成带有标签的 TypeScript 客户端
+
+如果您使用标签为FastAPI应用生成客户端,它通常也会根据标签分割客户端代码。
+
+通过这种方式,您将能够为客户端代码进行正确地排序和分组:
+
+

+
+在这个案例中,您有:
+
+* `ItemsService`
+* `UsersService`
+
+### 客户端方法名称
+
+现在生成的方法名像 `createItemItemsPost` 看起来不太简洁:
+
+```TypeScript
+ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
+```
+
+...这是因为客户端生成器为每个 *路径操作* 使用OpenAPI的内部 **操作 ID(operation ID)**。
+
+OpenAPI要求每个操作 ID 在所有 *路径操作* 中都是唯一的,因此 FastAPI 使用**函数名**、**路径**和**HTTP方法/操作**来生成此操作ID,因为这样可以确保这些操作 ID 是唯一的。
+
+但接下来我会告诉你如何改进。 🤓
+
+## 自定义操作ID和更好的方法名
+
+您可以**修改**这些操作ID的**生成**方式,以使其更简洁,并在客户端中具有**更简洁的方法名称**。
+
+在这种情况下,您必须确保每个操作ID在其他方面是**唯一**的。
+
+例如,您可以确保每个*路径操作*都有一个标签,然后根据**标签**和*路径操作***名称**(函数名)来生成操作ID。
+
+### 自定义生成唯一ID函数
+
+FastAPI为每个*路径操作*使用一个**唯一ID**,它用于**操作ID**,也用于任何所需自定义模型的名称,用于请求或响应。
+
+你可以自定义该函数。它接受一个 `APIRoute` 对象作为输入,并输出一个字符串。
+
+例如,以下是一个示例,它使用第一个标签(你可能只有一个标签)和*路径操作*名称(函数名)。
+
+然后,你可以将这个自定义函数作为 `generate_unique_id_function` 参数传递给 **FastAPI**:
+
+{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *}
+
+### 使用自定义操作ID生成TypeScript客户端
+
+现在,如果你再次生成客户端,你会发现它具有改善的方法名称:
+
+

+
+正如你所见,现在方法名称中只包含标签和函数名,不再包含URL路径和HTTP操作的信息。
+
+### 预处理用于客户端生成器的OpenAPI规范
+
+生成的代码仍然存在一些**重复的信息**。
+
+我们已经知道该方法与 **items** 相关,因为它在 `ItemsService` 中(从标签中获取),但方法名中仍然有标签名作为前缀。😕
+
+一般情况下对于OpenAPI,我们可能仍然希望保留它,因为这将确保操作ID是**唯一的**。
+
+但对于生成的客户端,我们可以在生成客户端之前**修改** OpenAPI 操作ID,以使方法名称更加美观和**简洁**。
+
+我们可以将 OpenAPI JSON 下载到一个名为`openapi.json`的文件中,然后使用以下脚本**删除此前缀的标签**:
+
+{* ../../docs_src/generate_clients/tutorial004.py *}
+
+通过这样做,操作ID将从类似于 `items-get_items` 的名称重命名为 `get_items` ,这样客户端生成器就可以生成更简洁的方法名称。
+
+### 使用预处理的OpenAPI生成TypeScript客户端
+
+现在,由于最终结果保存在文件openapi.json中,你可以修改 package.json 文件以使用此本地文件,例如:
+
+```JSON hl_lines="7"
+{
+ "name": "frontend-app",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "generate-client": "openapi-ts --input ./openapi.json --output ./src/client --client axios"
+ },
+ "author": "",
+ "license": "",
+ "devDependencies": {
+ "@hey-api/openapi-ts": "^0.27.38",
+ "typescript": "^4.6.2"
+ }
+}
+```
+
+生成新的客户端之后,你现在将拥有**清晰的方法名称**,具备**自动补全**、**错误提示**等功能:
+
+

+
+## 优点
+
+当使用自动生成的客户端时,你将获得以下的自动补全功能:
+
+* 方法。
+* 请求体中的数据、查询参数等。
+* 响应数据。
+
+你还将获得针对所有内容的错误提示。
+
+每当你更新后端代码并**重新生成**前端代码时,新的*路径操作*将作为方法可用,旧的方法将被删除,并且其他任何更改将反映在生成的代码中。 🤓
+
+这也意味着如果有任何更改,它将自动**反映**在客户端代码中。如果你**构建**客户端,在使用的数据上存在**不匹配**时,它将报错。
+
+因此,你将在开发周期的早期**检测到许多错误**,而不必等待错误在生产环境中向最终用户展示,然后尝试调试问题所在。 ✨
diff --git a/docs/zh/docs/advanced/index.md b/docs/zh/docs/advanced/index.md
index d71838cd7..6525802fc 100644
--- a/docs/zh/docs/advanced/index.md
+++ b/docs/zh/docs/advanced/index.md
@@ -1,18 +1,21 @@
-# 高级用户指南 - 简介
+# 高级用户指南
## 额外特性
-主要的教程 [教程 - 用户指南](../tutorial/){.internal-link target=_blank} 应该足以让你了解 **FastAPI** 的所有主要特性。
+主要的教程 [教程 - 用户指南](../tutorial/index.md){.internal-link target=_blank} 应该足以让你了解 **FastAPI** 的所有主要特性。
你会在接下来的章节中了解到其他的选项、配置以及额外的特性。
-!!! tip
- 接下来的章节**并不一定是**「高级的」。
+/// tip
- 而且对于你的使用场景来说,解决方案很可能就在其中。
+接下来的章节**并不一定是**「高级的」。
+
+而且对于你的使用场景来说,解决方案很可能就在其中。
+
+///
## 先阅读教程
-你可能仍会用到 **FastAPI** 主教程 [教程 - 用户指南](../tutorial/){.internal-link target=_blank} 中的大多数特性。
+你可能仍会用到 **FastAPI** 主教程 [教程 - 用户指南](../tutorial/index.md){.internal-link target=_blank} 中的大多数特性。
-接下来的章节我们认为你已经读过 [教程 - 用户指南](../tutorial/){.internal-link target=_blank},并且假设你已经知晓其中主要思想。
+接下来的章节我们认为你已经读过 [教程 - 用户指南](../tutorial/index.md){.internal-link target=_blank},并且假设你已经知晓其中主要思想。
diff --git a/docs/zh/docs/advanced/middleware.md b/docs/zh/docs/advanced/middleware.md
new file mode 100644
index 000000000..c7b15b929
--- /dev/null
+++ b/docs/zh/docs/advanced/middleware.md
@@ -0,0 +1,95 @@
+# 高级中间件
+
+用户指南介绍了如何为应用添加[自定义中间件](../tutorial/middleware.md){.internal-link target=_blank} 。
+
+以及如何[使用 `CORSMiddleware` 处理 CORS](../tutorial/cors.md){.internal-link target=_blank}。
+
+本章学习如何使用其它中间件。
+
+## 添加 ASGI 中间件
+
+因为 **FastAPI** 基于 Starlette,且执行
ASGI 规范,所以可以使用任意 ASGI 中间件。
+
+中间件不必是专为 FastAPI 或 Starlette 定制的,只要遵循 ASGI 规范即可。
+
+总之,ASGI 中间件是类,并把 ASGI 应用作为第一个参数。
+
+因此,有些第三方 ASGI 中间件的文档推荐以如下方式使用中间件:
+
+```Python
+from unicorn import UnicornMiddleware
+
+app = SomeASGIApp()
+
+new_app = UnicornMiddleware(app, some_config="rainbow")
+```
+
+但 FastAPI(实际上是 Starlette)提供了一种更简单的方式,能让内部中间件在处理服务器错误的同时,还能让自定义异常处理器正常运作。
+
+为此,要使用 `app.add_middleware()` (与 CORS 中的示例一样)。
+
+```Python
+from fastapi import FastAPI
+from unicorn import UnicornMiddleware
+
+app = FastAPI()
+
+app.add_middleware(UnicornMiddleware, some_config="rainbow")
+```
+
+`app.add_middleware()` 的第一个参数是中间件的类,其它参数则是要传递给中间件的参数。
+
+## 集成中间件
+
+**FastAPI** 为常见用例提供了一些中间件,下面介绍怎么使用这些中间件。
+
+/// note | 技术细节
+
+以下几个示例中也可以使用 `from starlette.middleware.something import SomethingMiddleware`。
+
+**FastAPI** 在 `fastapi.middleware` 中提供的中间件只是为了方便开发者使用,但绝大多数可用的中间件都直接继承自 Starlette。
+
+///
+
+## `HTTPSRedirectMiddleware`
+
+强制所有传入请求必须是 `https` 或 `wss`。
+
+任何传向 `http` 或 `ws` 的请求都会被重定向至安全方案。
+
+{* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *}
+
+## `TrustedHostMiddleware`
+
+强制所有传入请求都必须正确设置 `Host` 请求头,以防 HTTP 主机头攻击。
+
+{* ../../docs_src/advanced_middleware/tutorial002.py hl[2,6:8] *}
+
+支持以下参数:
+
+* `allowed_hosts` - 允许的域名(主机名)列表。`*.example.com` 等通配符域名可以匹配子域名,或使用 `allowed_hosts=["*"]` 允许任意主机名,或省略中间件。
+
+如果传入的请求没有通过验证,则发送 `400` 响应。
+
+## `GZipMiddleware`
+
+处理 `Accept-Encoding` 请求头中包含 `gzip` 请求的 GZip 响应。
+
+中间件会处理标准响应与流响应。
+
+{* ../../docs_src/advanced_middleware/tutorial003.py hl[2,6] *}
+
+支持以下参数:
+
+* `minimum_size` - 小于最小字节的响应不使用 GZip。 默认值是 `500`。
+
+## 其它中间件
+
+除了上述中间件外,FastAPI 还支持其它ASGI 中间件。
+
+例如:
+
+*
Uvicorn 的 `ProxyHeadersMiddleware`
+*
MessagePack
+
+其它可用中间件详见
Starlette 官档 - 中间件 及
ASGI Awesome 列表。
diff --git a/docs/zh/docs/advanced/openapi-callbacks.md b/docs/zh/docs/advanced/openapi-callbacks.md
new file mode 100644
index 000000000..f021eb10a
--- /dev/null
+++ b/docs/zh/docs/advanced/openapi-callbacks.md
@@ -0,0 +1,186 @@
+# OpenAPI 回调
+
+您可以创建触发外部 API 请求的*路径操作* API,这个外部 API 可以是别人创建的,也可以是由您自己创建的。
+
+API 应用调用外部 API 时的流程叫做**回调**。因为外部开发者编写的软件发送请求至您的 API,然后您的 API 要进行回调,并把请求发送至外部 API。
+
+此时,我们需要存档外部 API 的*信息*,比如应该有哪些*路径操作*,返回什么样的请求体,应该返回哪种响应等。
+
+## 使用回调的应用
+
+示例如下。
+
+假设要开发一个创建发票的应用。
+
+发票包括 `id`、`title`(可选)、`customer`、`total` 等属性。
+
+API 的用户 (外部开发者)要在您的 API 内使用 POST 请求创建一条发票记录。
+
+(假设)您的 API 将:
+
+* 把发票发送至外部开发者的消费者
+* 归集现金
+* 把通知发送至 API 的用户(外部开发者)
+ * 通过(从您的 API)发送 POST 请求至外部 API (即**回调**)来完成
+
+## 常规 **FastAPI** 应用
+
+添加回调前,首先看下常规 API 应用是什么样子。
+
+常规 API 应用包含接收 `Invoice` 请求体的*路径操作*,还有包含回调 URL 的查询参数 `callback_url`。
+
+这部分代码很常规,您对绝大多数代码应该都比较熟悉了:
+
+{* ../../docs_src/openapi_callbacks/tutorial001.py hl[10:14,37:54] *}
+
+/// tip | 提示
+
+`callback_url` 查询参数使用 Pydantic 的
URL 类型。
+
+///
+
+此处唯一比较新的内容是*路径操作装饰器*中的 `callbacks=invoices_callback_router.routes` 参数,下文介绍。
+
+## 存档回调
+
+实际的回调代码高度依赖于您自己的 API 应用。
+
+并且可能每个应用都各不相同。
+
+回调代码可能只有一两行,比如:
+
+```Python
+callback_url = "https://example.com/api/v1/invoices/events/"
+requests.post(callback_url, json={"description": "Invoice paid", "paid": True})
+```
+
+但回调最重要的部分可能是,根据 API 要发送给回调请求体的数据等内容,确保您的 API 用户(外部开发者)正确地实现*外部 API*。
+
+因此,我们下一步要做的就是添加代码,为从 API 接收回调的*外部 API*存档。
+
+这部分文档在 `/docs` 下的 Swagger API 文档中显示,并且会告诉外部开发者如何构建*外部 API*。
+
+本例没有实现回调本身(只是一行代码),只有文档部分。
+
+/// tip | 提示
+
+实际的回调只是 HTTP 请求。
+
+实现回调时,要使用
HTTPX 或
Requests。
+
+///
+
+## 编写回调文档代码
+
+应用不执行这部分代码,只是用它来*记录 外部 API* 。
+
+但,您已经知道用 **FastAPI** 创建自动 API 文档有多简单了。
+
+我们要使用与存档*外部 API* 相同的知识……通过创建外部 API 要实现的*路径操作*(您的 API 要调用的)。
+
+/// tip | 提示
+
+编写存档回调的代码时,假设您是*外部开发者*可能会用的上。并且您当前正在实现的是*外部 API*,不是*您自己的 API*。
+
+临时改变(为外部开发者的)视角能让您更清楚该如何放置*外部 API* 响应和请求体的参数与 Pydantic 模型等。
+
+///
+
+### 创建回调的 `APIRouter`
+
+首先,新建包含一些用于回调的 `APIRouter`。
+
+{* ../../docs_src/openapi_callbacks/tutorial001.py hl[5,26] *}
+
+### 创建回调*路径操作*
+
+创建回调*路径操作*也使用之前创建的 `APIRouter`。
+
+它看起来和常规 FastAPI *路径操作*差不多:
+
+* 声明要接收的请求体,例如,`body: InvoiceEvent`
+* 还要声明要返回的响应,例如,`response_model=InvoiceEventReceived`
+
+{* ../../docs_src/openapi_callbacks/tutorial001.py hl[17:19,22:23,29:33] *}
+
+回调*路径操作*与常规*路径操作*有两点主要区别:
+
+* 它不需要任何实际的代码,因为应用不会调用这段代码。它只是用于存档*外部 API*。因此,函数的内容只需要 `pass` 就可以了
+* *路径*可以包含
OpenAPI 3 表达式(详见下文),可以使用带参数的变量,以及发送至您的 API 的原始请求的部分
+
+### 回调路径表达式
+
+回调*路径*支持包含发送给您的 API 的原始请求的部分的
OpenAPI 3 表达式。
+
+本例中是**字符串**:
+
+```Python
+"{$callback_url}/invoices/{$request.body.id}"
+```
+
+因此,如果您的 API 用户(外部开发者)发送请求到您的 API:
+
+```
+https://yourapi.com/invoices/?callback_url=https://www.external.org/events
+```
+
+使用如下 JSON 请求体:
+
+```JSON
+{
+ "id": "2expen51ve",
+ "customer": "Mr. Richie Rich",
+ "total": "9999"
+}
+```
+
+然后,您的 API 就会处理发票,并在某个点之后,发送回调请求至 `callback_url`(外部 API):
+
+```
+https://www.external.org/events/invoices/2expen51ve
+```
+
+JSON 请求体包含如下内容:
+
+```JSON
+{
+ "description": "Payment celebration",
+ "paid": true
+}
+```
+
+它会预期*外部 API* 的响应包含如下 JSON 请求体:
+
+```JSON
+{
+ "ok": true
+}
+```
+
+/// tip | 提示
+
+注意,回调 URL包含 `callback_url` (`https://www.external.org/events`)中的查询参数,还有 JSON 请求体内部的发票 ID(`2expen51ve`)。
+
+///
+
+### 添加回调路由
+
+至此,在上文创建的回调路由里就包含了*回调路径操作*(外部开发者要在外部 API 中实现)。
+
+现在使用 API *路径操作装饰器*的参数 `callbacks`,从回调路由传递属性 `.routes`(实际上只是路由/路径操作的**列表**):
+
+{* ../../docs_src/openapi_callbacks/tutorial001.py hl[36] *}
+
+/// tip | 提示
+
+注意,不能把路由本身(`invoices_callback_router`)传递给 `callback=`,要传递 `invoices_callback_router.routes` 中的 `.routes` 属性。
+
+///
+
+### 查看文档
+
+现在,使用 Uvicorn 启动应用,打开
http://127.0.0.1:8000/docs。
+
+就能看到文档的*路径操作*已经包含了**回调**的内容以及*外部 API*:
+
+

diff --git a/docs/zh/docs/advanced/openapi-webhooks.md b/docs/zh/docs/advanced/openapi-webhooks.md
new file mode 100644
index 000000000..92ae8db15
--- /dev/null
+++ b/docs/zh/docs/advanced/openapi-webhooks.md
@@ -0,0 +1,55 @@
+# OpenAPI 网络钩子
+
+有些情况下,您可能想告诉您的 API **用户**,您的应用程序可以携带一些数据调用*他们的*应用程序(给它们发送请求),通常是为了**通知**某种**事件**。
+
+这意味着,除了您的用户向您的 API 发送请求的一般情况,**您的 API**(或您的应用)也可以向**他们的系统**(他们的 API、他们的应用)**发送请求**。
+
+这通常被称为**网络钩子**(Webhook)。
+
+## 使用网络钩子的步骤
+
+通常的过程是**您**在代码中**定义**要发送的消息,即**请求的主体**。
+
+您还需要以某种方式定义您的应用程序将在**何时**发送这些请求或事件。
+
+**用户**会以某种方式(例如在某个网页仪表板上)定义您的应用程序发送这些请求应该使用的 **URL**。
+
+所有关于注册网络钩子的 URL 的**逻辑**以及发送这些请求的实际代码都由您决定。您可以在**自己的代码**中以任何想要的方式来编写它。
+
+## 使用 `FastAPI` 和 OpenAPI 文档化网络钩子
+
+使用 **FastAPI**,您可以利用 OpenAPI 来自定义这些网络钩子的名称、您的应用可以发送的 HTTP 操作类型(例如 `POST`、`PUT` 等)以及您的应用将发送的**请求体**。
+
+这能让您的用户更轻松地**实现他们的 API** 来接收您的**网络钩子**请求,他们甚至可能能够自动生成一些自己的 API 代码。
+
+/// info
+
+网络钩子在 OpenAPI 3.1.0 及以上版本中可用,FastAPI `0.99.0` 及以上版本支持。
+
+///
+
+## 带有网络钩子的应用程序
+
+当您创建一个 **FastAPI** 应用程序时,有一个 `webhooks` 属性可以用来定义网络钩子,方式与您定义*路径操作*的时候相同,例如使用 `@app.webhooks.post()` 。
+
+{* ../../docs_src/openapi_webhooks/tutorial001.py hl[9:13,36:53] *}
+
+您定义的网络钩子将被包含在 `OpenAPI` 的架构中,并出现在自动生成的**文档 UI** 中。
+
+/// info
+
+`app.webhooks` 对象实际上只是一个 `APIRouter` ,与您在使用多个文件来构建应用程序时所使用的类型相同。
+
+///
+
+请注意,使用网络钩子时,您实际上并没有声明一个*路径*(比如 `/items/` ),您传递的文本只是这个网络钩子的**标识符**(事件的名称)。例如在 `@app.webhooks.post("new-subscription")` 中,网络钩子的名称是 `new-subscription` 。
+
+这是因为我们预计**您的用户**会以其他方式(例如通过网页仪表板)来定义他们希望接收网络钩子的请求的实际 **URL 路径**。
+
+### 查看文档
+
+现在您可以启动您的应用程序并访问
http://127.0.0.1:8000/docs.
+
+您会看到您的文档不仅有正常的*路径操作*显示,现在还多了一些**网络钩子**:
+
+

diff --git a/docs/zh/docs/advanced/path-operation-advanced-configuration.md b/docs/zh/docs/advanced/path-operation-advanced-configuration.md
index 7da9f251e..12600eddb 100644
--- a/docs/zh/docs/advanced/path-operation-advanced-configuration.md
+++ b/docs/zh/docs/advanced/path-operation-advanced-configuration.md
@@ -2,16 +2,17 @@
## OpenAPI 的 operationId
-!!! warning
- 如果你并非 OpenAPI 的「专家」,你可能不需要这部分内容。
+/// warning
+
+如果你并非 OpenAPI 的「专家」,你可能不需要这部分内容。
+
+///
你可以在路径操作中通过参数 `operation_id` 设置要使用的 OpenAPI `operationId`。
务必确保每个操作路径的 `operation_id` 都是唯一的。
-```Python hl_lines="6"
-{!../../../docs_src/path_operation_advanced_configuration/tutorial001.py!}
-```
+{* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *}
### 使用 *路径操作函数* 的函数名作为 operationId
@@ -19,25 +20,27 @@
你应该在添加了所有 *路径操作* 之后执行此操作。
-```Python hl_lines="2 12 13 14 15 16 17 18 19 20 21 24"
-{!../../../docs_src/path_operation_advanced_configuration/tutorial002.py!}
-```
+{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2,12,13,14,15,16,17,18,19,20,21,24] *}
+
+/// tip
+
+如果你手动调用 `app.openapi()`,你应该在此之前更新 `operationId`。
+
+///
+
+/// warning
-!!! tip
- 如果你手动调用 `app.openapi()`,你应该在此之前更新 `operationId`。
+如果你这样做,务必确保你的每个 *路径操作函数* 的名字唯一。
-!!! warning
- 如果你这样做,务必确保你的每个 *路径操作函数* 的名字唯一。
+即使它们在不同的模块中(Python 文件)。
- 即使它们在不同的模块中(Python 文件)。
+///
## 从 OpenAPI 中排除
使用参数 `include_in_schema` 并将其设置为 `False` ,来从生成的 OpenAPI 方案中排除一个 *路径操作*(这样一来,就从自动化文档系统中排除掉了)。
-```Python hl_lines="6"
-{!../../../docs_src/path_operation_advanced_configuration/tutorial003.py!}
-```
+{* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *}
## docstring 的高级描述
@@ -48,6 +51,4 @@
剩余部分不会出现在文档中,但是其他工具(比如 Sphinx)可以使用剩余部分。
-```Python hl_lines="19 20 21 22 23 24 25 26 27 28 29"
-{!../../../docs_src/path_operation_advanced_configuration/tutorial004.py!}
-```
+{* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19,20,21,22,23,24,25,26,27,28,29] *}
diff --git a/docs/zh/docs/advanced/response-change-status-code.md b/docs/zh/docs/advanced/response-change-status-code.md
new file mode 100644
index 000000000..cc1f2a73e
--- /dev/null
+++ b/docs/zh/docs/advanced/response-change-status-code.md
@@ -0,0 +1,29 @@
+# 响应 - 更改状态码
+
+你可能之前已经了解到,你可以设置默认的[响应状态码](../tutorial/response-status-code.md){.internal-link target=_blank}。
+
+但在某些情况下,你需要返回一个不同于默认值的状态码。
+
+## 使用场景
+
+例如,假设你想默认返回一个HTTP状态码为“OK”`200`。
+
+但如果数据不存在,你想创建它,并返回一个HTTP状态码为“CREATED”`201`。
+
+但你仍然希望能够使用`response_model`过滤和转换你返回的数据。
+
+对于这些情况,你可以使用一个`Response`参数。
+
+## 使用 `Response` 参数
+
+你可以在你的*路径操作函数*中声明一个`Response`类型的参数(就像你可以为cookies和头部做的那样)。
+
+然后你可以在这个*临时*响应对象中设置`status_code`。
+
+{* ../../docs_src/response_change_status_code/tutorial001.py hl[1,9,12] *}
+
+然后你可以像平常一样返回任何你需要的对象(例如一个`dict`或者一个数据库模型)。如果你声明了一个`response_model`,它仍然会被用来过滤和转换你返回的对象。
+
+**FastAPI**将使用这个临时响应来提取状态码(也包括cookies和头部),并将它们放入包含你返回的值的最终响应中,该响应由任何`response_model`过滤。
+
+你也可以在依赖项中声明`Response`参数,并在其中设置状态码。但请注意,最后设置的状态码将会生效。
diff --git a/docs/zh/docs/advanced/response-cookies.md b/docs/zh/docs/advanced/response-cookies.md
new file mode 100644
index 000000000..d4b93d003
--- /dev/null
+++ b/docs/zh/docs/advanced/response-cookies.md
@@ -0,0 +1,49 @@
+# 响应Cookies
+
+## 使用 `Response` 参数
+
+你可以在 *路径函数* 中定义一个类型为 `Response`的参数,这样你就可以在这个临时响应对象中设置cookie了。
+
+{* ../../docs_src/response_cookies/tutorial002.py hl[1,8:9] *}
+
+而且你还可以根据你的需要响应不同的对象,比如常用的 `dict`,数据库model等。
+
+如果你定义了 `response_model`,程序会自动根据`response_model`来过滤和转换你响应的对象。
+
+**FastAPI** 会使用这个 *临时* 响应对象去装在这些cookies信息 (同样还有headers和状态码等信息), 最终会将这些信息和通过`response_model`转化过的数据合并到最终的响应里。
+
+你也可以在depend中定义`Response`参数,并设置cookie和header。
+
+## 直接响应 `Response`
+
+你还可以在直接响应`Response`时直接创建cookies。
+
+你可以参考[Return a Response Directly](response-directly.md){.internal-link target=_blank}来创建response
+
+然后设置Cookies,并返回:
+
+{* ../../docs_src/response_cookies/tutorial001.py hl[10:12] *}
+
+/// tip
+
+需要注意,如果你直接反馈一个response对象,而不是使用`Response`入参,FastAPI则会直接反馈你封装的response对象。
+
+所以你需要确保你响应数据类型的正确性,如:你可以使用`JSONResponse`来兼容JSON的场景。
+
+同时,你也应当仅反馈通过`response_model`过滤过的数据。
+
+///
+
+### 更多信息
+
+/// note | 技术细节
+
+你也可以使用`from starlette.responses import Response` 或者 `from starlette.responses import JSONResponse`。
+
+为了方便开发者,**FastAPI** 封装了相同数据类型,如`starlette.responses` 和 `fastapi.responses`。不过大部分response对象都是直接引用自Starlette。
+
+因为`Response`对象可以非常便捷的设置headers和cookies,所以 **FastAPI** 同时也封装了`fastapi.Response`。
+
+///
+
+如果你想查看所有可用的参数和选项,可以参考
Starlette帮助文档
diff --git a/docs/zh/docs/advanced/response-directly.md b/docs/zh/docs/advanced/response-directly.md
index 05926a9c8..4d9cd53f2 100644
--- a/docs/zh/docs/advanced/response-directly.md
+++ b/docs/zh/docs/advanced/response-directly.md
@@ -10,12 +10,15 @@
直接返回响应可能会有用处,比如返回自定义的响应头和 cookies。
-## 返回 `Response`
+## 返回 `Response`
事实上,你可以返回任意 `Response` 或者任意 `Response` 的子类。
-!!! tip "小贴士"
- `JSONResponse` 本身是一个 `Response` 的子类。
+/// tip | 小贴士
+
+`JSONResponse` 本身是一个 `Response` 的子类。
+
+///
当你返回一个 `Response` 时,**FastAPI** 会直接传递它。
@@ -32,14 +35,15 @@
对于这些情况,在将数据传递给响应之前,你可以使用 `jsonable_encoder` 来转换你的数据。
-```Python hl_lines="4 6 20 21"
-{!../../../docs_src/response_directly/tutorial001.py!}
-```
+{* ../../docs_src/response_directly/tutorial001.py hl[4,6,20,21] *}
+
+/// note | 技术细节
-!!! note "技术细节"
- 你也可以使用 `from starlette.responses import JSONResponse`。
+你也可以使用 `from starlette.responses import JSONResponse`。
- 出于方便,**FastAPI** 会提供与 `starlette.responses` 相同的 `fastapi.responses` 给开发者。但是大多数可用的响应都直接来自 Starlette。
+出于方便,**FastAPI** 会提供与 `starlette.responses` 相同的 `fastapi.responses` 给开发者。但是大多数可用的响应都直接来自 Starlette。
+
+///
## 返回自定义 `Response`
@@ -51,9 +55,7 @@
你可以把你的 XML 内容放到一个字符串中,放到一个 `Response` 中,然后返回。
-```Python hl_lines="1 18"
-{!../../../docs_src/response_directly/tutorial002.py!}
-```
+{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
## 说明
@@ -62,4 +64,3 @@
但是你仍可以参考 [OpenApI 中的额外响应](additional-responses.md){.internal-link target=_blank} 给响应编写文档。
在后续的章节中你可以了解到如何使用/声明这些自定义的 `Response` 的同时还保留自动化的数据转换和文档等。
-
diff --git a/docs/zh/docs/advanced/response-headers.md b/docs/zh/docs/advanced/response-headers.md
new file mode 100644
index 000000000..fe2cb0da8
--- /dev/null
+++ b/docs/zh/docs/advanced/response-headers.md
@@ -0,0 +1,39 @@
+# 响应头
+
+## 使用 `Response` 参数
+
+你可以在你的*路径操作函数*中声明一个`Response`类型的参数(就像你可以为cookies做的那样)。
+
+然后你可以在这个*临时*响应对象中设置头部。
+{* ../../docs_src/response_headers/tutorial002.py hl[1,7:8] *}
+
+然后你可以像平常一样返回任何你需要的对象(例如一个`dict`或者一个数据库模型)。如果你声明了一个`response_model`,它仍然会被用来过滤和转换你返回的对象。
+
+**FastAPI**将使用这个临时响应来提取头部(也包括cookies和状态码),并将它们放入包含你返回的值的最终响应中,该响应由任何`response_model`过滤。
+
+你也可以在依赖项中声明`Response`参数,并在其中设置头部(和cookies)。
+
+## 直接返回 `Response`
+
+你也可以在直接返回`Response`时添加头部。
+
+按照[直接返回响应](response-directly.md){.internal-link target=_blank}中所述创建响应,并将头部作为附加参数传递:
+
+{* ../../docs_src/response_headers/tutorial001.py hl[10:12] *}
+
+
+/// note | 技术细节
+
+你也可以使用`from starlette.responses import Response`或`from starlette.responses import JSONResponse`。
+
+**FastAPI**提供了与`fastapi.responses`相同的`starlette.responses`,只是为了方便开发者。但是,大多数可用的响应都直接来自Starlette。
+
+由于`Response`经常用于设置头部和cookies,因此**FastAPI**还在`fastapi.Response`中提供了它。
+
+///
+
+## 自定义头部
+
+请注意,可以使用'X-'前缀添加自定义专有头部。
+
+但是,如果你有自定义头部,你希望浏览器中的客户端能够看到它们,你需要将它们添加到你的CORS配置中(在[CORS(跨源资源共享)](../tutorial/cors.md){.internal-link target=_blank}中阅读更多),使用在
Starlette的CORS文档中记录的`expose_headers`参数。
diff --git a/docs/zh/docs/advanced/security/http-basic-auth.md b/docs/zh/docs/advanced/security/http-basic-auth.md
new file mode 100644
index 000000000..599429f9d
--- /dev/null
+++ b/docs/zh/docs/advanced/security/http-basic-auth.md
@@ -0,0 +1,107 @@
+# HTTP 基础授权
+
+最简单的用例是使用 HTTP 基础授权(HTTP Basic Auth)。
+
+在 HTTP 基础授权中,应用需要请求头包含用户名与密码。
+
+如果没有接收到 HTTP 基础授权,就返回 HTTP 401 `"Unauthorized"` 错误。
+
+并返回含 `Basic` 值的请求头 `WWW-Authenticate`以及可选的 `realm` 参数。
+
+HTTP 基础授权让浏览器显示内置的用户名与密码提示。
+
+输入用户名与密码后,浏览器会把它们自动发送至请求头。
+
+## 简单的 HTTP 基础授权
+
+* 导入 `HTTPBasic` 与 `HTTPBasicCredentials`
+* 使用 `HTTPBasic` 创建**安全概图**
+* 在*路径操作*的依赖项中使用 `security`
+* 返回类型为 `HTTPBasicCredentials` 的对象:
+ * 包含发送的 `username` 与 `password`
+
+{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *}
+
+第一次打开 URL(或在 API 文档中点击 **Execute** 按钮)时,浏览器要求输入用户名与密码:
+
+

+
+## 检查用户名
+
+以下是更完整的示例。
+
+使用依赖项检查用户名与密码是否正确。
+
+为此要使用 Python 标准模块
`secrets` 检查用户名与密码。
+
+`secrets.compare_digest()` 需要仅包含 ASCII 字符(英语字符)的 `bytes` 或 `str`,这意味着它不适用于像`á`一样的字符,如 `Sebastián`。
+
+为了解决这个问题,我们首先将 `username` 和 `password` 转换为使用 UTF-8 编码的 `bytes` 。
+
+然后我们可以使用 `secrets.compare_digest()` 来确保 `credentials.username` 是 `"stanleyjobson"`,且 `credentials.password` 是`"swordfish"`。
+
+{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *}
+
+这类似于:
+
+```Python
+if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"):
+ # Return some error
+ ...
+```
+
+但使用 `secrets.compare_digest()`,可以防御**时差攻击**,更加安全。
+
+### 时差攻击
+
+什么是**时差攻击**?
+
+假设攻击者试图猜出用户名与密码。
+
+他们发送用户名为 `johndoe`,密码为 `love123` 的请求。
+
+然后,Python 代码执行如下操作:
+
+```Python
+if "johndoe" == "stanleyjobson" and "love123" == "swordfish":
+ ...
+```
+
+但就在 Python 比较完 `johndoe` 的第一个字母 `j` 与 `stanleyjobson` 的 `s` 时,Python 就已经知道这两个字符串不相同了,它会这么想,**没必要浪费更多时间执行剩余字母的对比计算了**。应用立刻就会返回**错误的用户或密码**。
+
+但接下来,攻击者继续尝试 `stanleyjobsox` 和 密码 `love123`。
+
+应用代码会执行类似下面的操作:
+
+```Python
+if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish":
+ ...
+```
+
+此时,Python 要对比 `stanleyjobsox` 与 `stanleyjobson` 中的 `stanleyjobso`,才能知道这两个字符串不一样。因此会多花费几微秒来返回**错误的用户或密码**。
+
+#### 反应时间对攻击者的帮助
+
+通过服务器花费了更多微秒才发送**错误的用户或密码**响应,攻击者会知道猜对了一些内容,起码开头字母是正确的。
+
+然后,他们就可以放弃 `johndoe`,再用类似 `stanleyjobsox` 的内容进行尝试。
+
+#### **专业**攻击
+
+当然,攻击者不用手动操作,而是编写每秒能执行成千上万次测试的攻击程序,每次都会找到更多正确字符。
+
+但是,在您的应用的**帮助**下,攻击者利用时间差,就能在几分钟或几小时内,以这种方式猜出正确的用户名和密码。
+
+#### 使用 `secrets.compare_digest()` 修补
+
+在此,代码中使用了 `secrets.compare_digest()`。
+
+简单的说,它使用相同的时间对比 `stanleyjobsox` 和 `stanleyjobson`,还有 `johndoe` 和 `stanleyjobson`。对比密码时也一样。
+
+在代码中使用 `secrets.compare_digest()` ,就可以安全地防御全面攻击了。
+
+### 返回错误
+
+检测到凭证不正确后,返回 `HTTPException` 及状态码 401(与无凭证时返回的内容一样),并添加请求头 `WWW-Authenticate`,让浏览器再次显示登录提示:
+
+{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *}
diff --git a/docs/zh/docs/advanced/security/index.md b/docs/zh/docs/advanced/security/index.md
new file mode 100644
index 000000000..267e7ced7
--- /dev/null
+++ b/docs/zh/docs/advanced/security/index.md
@@ -0,0 +1,19 @@
+# 高级安全
+
+## 附加特性
+
+除 [教程 - 用户指南: 安全性](../../tutorial/security/index.md){.internal-link target=_blank} 中涵盖的功能之外,还有一些额外的功能来处理安全性.
+
+/// tip | 小贴士
+
+接下来的章节 **并不一定是 "高级的"**.
+
+而且对于你的使用场景来说,解决方案很可能就在其中。
+
+///
+
+## 先阅读教程
+
+接下来的部分假设你已经阅读了主要的 [教程 - 用户指南: 安全性](../../tutorial/security/index.md){.internal-link target=_blank}.
+
+它们都基于相同的概念,但支持一些额外的功能.
diff --git a/docs/zh/docs/advanced/security/oauth2-scopes.md b/docs/zh/docs/advanced/security/oauth2-scopes.md
new file mode 100644
index 000000000..784c38490
--- /dev/null
+++ b/docs/zh/docs/advanced/security/oauth2-scopes.md
@@ -0,0 +1,274 @@
+# OAuth2 作用域
+
+**FastAPI** 无缝集成 OAuth2 作用域(`Scopes`),可以直接使用。
+
+作用域是更精密的权限系统,遵循 OAuth2 标准,与 OpenAPI 应用(和 API 自动文档)集成。
+
+OAuth2 也是脸书、谷歌、GitHub、微软、推特等第三方身份验证应用使用的机制。这些身份验证应用在用户登录应用时使用 OAuth2 提供指定权限。
+
+脸书、谷歌、GitHub、微软、推特就是 OAuth2 作用域登录。
+
+本章介绍如何在 **FastAPI** 应用中使用 OAuth2 作用域管理验证与授权。
+
+/// warning | 警告
+
+本章内容较难,刚接触 FastAPI 的新手可以跳过。
+
+OAuth2 作用域不是必需的,没有它,您也可以处理身份验证与授权。
+
+但 OAuth2 作用域与 API(通过 OpenAPI)及 API 文档集成地更好。
+
+不管怎么说,**FastAPI** 支持在代码中使用作用域或其它安全/授权需求项。
+
+很多情况下,OAuth2 作用域就像一把牛刀。
+
+但如果您确定要使用作用域,或对它有兴趣,请继续阅读。
+
+///
+
+## OAuth2 作用域与 OpenAPI
+
+OAuth2 规范的**作用域**是由空格分割的字符串组成的列表。
+
+这些字符串支持任何格式,但不能包含空格。
+
+作用域表示的是**权限**。
+
+OpenAPI 中(例如 API 文档)可以定义**安全方案**。
+
+这些安全方案在使用 OAuth2 时,还可以声明和使用作用域。
+
+**作用域**只是(不带空格的)字符串。
+
+常用于声明特定安全权限,例如:
+
+* 常见用例为,`users:read` 或 `users:write`
+* 脸书和 Instagram 使用 `instagram_basic`
+* 谷歌使用 `https://www.googleapis.com/auth/drive`
+
+/// info | 说明
+
+OAuth2 中,**作用域**只是声明特定权限的字符串。
+
+是否使用冒号 `:` 等符号,或是不是 URL 并不重要。
+
+这些细节只是特定的实现方式。
+
+对 OAuth2 来说,它们都只是字符串而已。
+
+///
+
+## 全局纵览
+
+首先,快速浏览一下以下代码与**用户指南**中 [OAuth2 实现密码哈希与 Bearer JWT 令牌验证](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}一章中代码的区别。以下代码使用 OAuth2 作用域:
+
+{* ../../docs_src/security/tutorial005.py hl[2,4,8,12,46,64,105,107:115,121:124,128:134,139,153] *}
+
+下面,我们逐步说明修改的代码内容。
+
+## OAuth2 安全方案
+
+第一个修改的地方是,使用两个作用域 `me` 和 `items ` 声明 OAuth2 安全方案。
+
+`scopes` 参数接收**字典**,键是作用域、值是作用域的描述:
+
+{* ../../docs_src/security/tutorial005.py hl[62:65] *}
+
+因为声明了作用域,所以登录或授权时会在 API 文档中显示。
+
+此处,选择给予访问权限的作用域: `me` 和 `items`。
+
+这也是使用脸书、谷歌、GitHub 登录时的授权机制。
+
+

+
+## JWT 令牌作用域
+
+现在,修改令牌*路径操作*,返回请求的作用域。
+
+此处仍然使用 `OAuth2PasswordRequestForm`。它包含类型为**字符串列表**的 `scopes` 属性,且`scopes` 属性中包含要在请求里接收的每个作用域。
+
+这样,返回的 JWT 令牌中就包含了作用域。
+
+/// danger | 危险
+
+为了简明起见,本例把接收的作用域直接添加到了令牌里。
+
+但在您的应用中,为了安全,应该只把作用域添加到确实需要作用域的用户,或预定义的用户。
+
+///
+
+{* ../../docs_src/security/tutorial005.py hl[153] *}
+
+## 在*路径操作*与依赖项中声明作用域
+
+接下来,为*路径操作* `/users/me/items/` 声明作用域 `items`。
+
+为此,要从 `fastapi` 中导入并使用 `Security` 。
+
+`Security` 声明依赖项的方式和 `Depends` 一样,但 `Security` 还能接收作用域(字符串)列表类型的参数 `scopes`。
+
+此处使用与 `Depends` 相同的方式,把依赖项函数 `get_current_active_user` 传递给 `Security`。
+
+同时,还传递了作用域**列表**,本例中只传递了一个作用域:`items`(此处支持传递更多作用域)。
+
+依赖项函数 `get_current_active_user` 还能声明子依赖项,不仅可以使用 `Depends`,也可以使用 `Security`。声明子依赖项函数(`get_current_user`)及更多作用域。
+
+本例要求使用作用域 `me`(还可以使用更多作用域)。
+
+/// note | 笔记
+
+不必在不同位置添加不同的作用域。
+
+本例使用的这种方式只是为了展示 **FastAPI** 如何处理在不同层级声明的作用域。
+
+///
+
+{* ../../docs_src/security/tutorial005.py hl[4,139,166] *}
+
+/// info | 技术细节
+
+`Security` 实际上是 `Depends` 的子类,而且只比 `Depends` 多一个参数。
+
+但使用 `Security` 代替 `Depends`,**FastAPI** 可以声明安全作用域,并在内部使用这些作用域,同时,使用 OpenAPI 存档 API。
+
+但实际上,从 `fastapi` 导入的 `Query`、`Path`、`Depends`、`Security` 等对象,只是返回特殊类的函数。
+
+///
+
+## 使用 `SecurityScopes`
+
+修改依赖项 `get_current_user`。
+
+这是上面的依赖项使用的依赖项。
+
+这里使用的也是之前创建的 OAuth2 方案,并把它声明为依赖项:`oauth2_scheme`。
+
+该依赖项函数本身不需要作用域,因此,可以使用 `Depends` 和 `oauth2_scheme`。不需要指定安全作用域时,不必使用 `Security`。
+
+此处还声明了从 `fastapi.security` 导入的 `SecurityScopes` 类型的特殊参数。
+
+`SecuriScopes` 类与 `Request` 类似(`Request` 用于直接提取请求对象)。
+
+{* ../../docs_src/security/tutorial005.py hl[8,105] *}
+
+## 使用 `scopes`
+
+参数 `security_scopes` 的类型是 `SecurityScopes`。
+
+它的属性 `scopes` 是作用域列表,所有依赖项都把它作为子依赖项。也就是说所有**依赖**……这听起来有些绕,后文会有解释。
+
+(类 `SecurityScopes` 的)`security_scopes` 对象还提供了单字符串类型的属性 `scope_str`,该属性是(要在本例中使用的)用空格分割的作用域。
+
+此处还创建了后续代码中要复用(`raise`)的 `HTTPException` 。
+
+该异常包含了作用域所需的(如有),以空格分割的字符串(使用 `scope_str`)。该字符串要放到包含作用域的 `WWW-Authenticate` 请求头中(这也是规范的要求)。
+
+{* ../../docs_src/security/tutorial005.py hl[105,107:115] *}
+
+## 校验 `username` 与数据形状
+
+我们可以校验是否获取了 `username`,并抽取作用域。
+
+然后,使用 Pydantic 模型校验数据(捕获 `ValidationError` 异常),如果读取 JWT 令牌或使用 Pydantic 模型验证数据时出错,就会触发之前创建的 `HTTPException` 异常。
+
+对此,要使用新的属性 `scopes` 更新 Pydantic 模型 `TokenData`。
+
+使用 Pydantic 验证数据可以确保数据中含有由作用域组成的**字符串列表**,以及 `username` 字符串等内容。
+
+反之,如果使用**字典**或其它数据结构,就有可能在后面某些位置破坏应用,形成安全隐患。
+
+还可以使用用户名验证用户,如果没有用户,也会触发之前创建的异常。
+
+{* ../../docs_src/security/tutorial005.py hl[46,116:127] *}
+
+## 校验 `scopes`
+
+接下来,校验所有依赖项和依赖要素(包括*路径操作*)所需的作用域。这些作用域包含在令牌的 `scopes` 里,如果不在其中就会触发 `HTTPException` 异常。
+
+为此,要使用包含所有作用域**字符串列表**的 `security_scopes.scopes`, 。
+
+{* ../../docs_src/security/tutorial005.py hl[128:134] *}
+
+## 依赖项树与作用域
+
+再次查看这个依赖项树与作用域。
+
+`get_current_active_user` 依赖项包含子依赖项 `get_current_user`,并在 `get_current_active_user`中声明了作用域 `"me"` 包含所需作用域列表 ,在 `security_scopes.scopes` 中传递给 `get_current_user`。
+
+*路径操作*自身也声明了作用域,`"items"`,这也是 `security_scopes.scopes` 列表传递给 `get_current_user` 的。
+
+依赖项与作用域的层级架构如下:
+
+* *路径操作* `read_own_items` 包含:
+ * 依赖项所需的作用域 `["items"]`:
+ * `get_current_active_user`:
+ * 依赖项函数 `get_current_active_user` 包含:
+ * 所需的作用域 `"me"` 包含依赖项:
+ * `get_current_user`:
+ * 依赖项函数 `get_current_user` 包含:
+ * 没有作用域需求其自身
+ * 依赖项使用 `oauth2_scheme`
+ * `security_scopes` 参数的类型是 `SecurityScopes`:
+ * `security_scopes` 参数的属性 `scopes` 是包含上述声明的所有作用域的**列表**,因此:
+ * `security_scopes.scopes` 包含用于*路径操作*的 `["me", "items"]`
+ * `security_scopes.scopes` 包含*路径操作* `read_users_me` 的 `["me"]`,因为它在依赖项里被声明
+ * `security_scopes.scopes` 包含用于*路径操作* `read_system_status` 的 `[]`(空列表),并且它的依赖项 `get_current_user` 也没有声明任何 `scope`
+
+/// tip | 提示
+
+此处重要且**神奇**的事情是,`get_current_user` 检查每个*路径操作*时可以使用不同的 `scopes` 列表。
+
+所有这些都依赖于在每个*路径操作*和指定*路径操作*的依赖树中的每个依赖项。
+
+///
+
+## `SecurityScopes` 的更多细节
+
+您可以任何位置或多个位置使用 `SecurityScopes`,不一定非得在**根**依赖项中使用。
+
+它总是在当前 `Security` 依赖项中和所有依赖因子对于**特定** *路径操作*和**特定**依赖树中安全作用域
+
+因为 `SecurityScopes` 包含所有由依赖项声明的作用域,可以在核心依赖函数中用它验证所需作用域的令牌,然后再在不同的*路径操作*中声明不同作用域需求。
+
+它们会为每个*路径操作*进行单独检查。
+
+## 查看文档
+
+打开 API 文档,进行身份验证,并指定要授权的作用域。
+
+

+
+没有选择任何作用域,也可以进行**身份验证**,但访问 `/uses/me` 或 `/users/me/items` 时,会显示没有足够的权限。但仍可以访问 `/status/`。
+
+如果选择了作用域 `me`,但没有选择作用域 `items`,则可以访问 `/users/me/`,但不能访问 `/users/me/items`。
+
+这就是通过用户提供的令牌使用第三方应用访问这些*路径操作*时会发生的情况,具体怎样取决于用户授予第三方应用的权限。
+
+## 关于第三方集成
+
+本例使用 OAuth2 **密码**流。
+
+这种方式适用于登录我们自己的应用,最好使用我们自己的前端。
+
+因为我们能控制自己的前端应用,可以信任它接收 `username` 与 `password`。
+
+但如果构建的是连接其它应用的 OAuth2 应用,比如具有与脸书、谷歌、GitHub 相同功能的第三方身份验证应用。那您就应该使用其它安全流。
+
+最常用的是隐式流。
+
+最安全的是代码流,但实现起来更复杂,而且需要更多步骤。因为它更复杂,很多第三方身份验证应用最终建议使用隐式流。
+
+/// note | 笔记
+
+每个身份验证应用都会采用不同方式会命名流,以便融合入自己的品牌。
+
+但归根结底,它们使用的都是 OAuth2 标准。
+
+///
+
+**FastAPI** 的 `fastapi.security.oauth2` 里包含了所有 OAuth2 身份验证流工具。
+
+## 装饰器 `dependencies` 中的 `Security`
+
+同样,您可以在装饰器的 `dependencies` 参数中定义 `Depends` 列表,(详见[路径操作装饰器依赖项](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank})),也可以把 `scopes` 与 `Security` 一起使用。
diff --git a/docs/zh/docs/advanced/settings.md b/docs/zh/docs/advanced/settings.md
new file mode 100644
index 000000000..e33da136f
--- /dev/null
+++ b/docs/zh/docs/advanced/settings.md
@@ -0,0 +1,397 @@
+# 设置和环境变量
+
+在许多情况下,您的应用程序可能需要一些外部设置或配置,例如密钥、数据库凭据、电子邮件服务的凭据等等。
+
+这些设置中的大多数是可变的(可以更改的),比如数据库的 URL。而且许多设置可能是敏感的,比如密钥。
+
+因此,通常会将它们提供为由应用程序读取的环境变量。
+
+## 环境变量
+
+/// tip
+
+如果您已经知道什么是"环境变量"以及如何使用它们,请随意跳到下面的下一节。
+
+///
+
+环境变量(也称为"env var")是一种存在于 Python 代码之外、存在于操作系统中的变量,可以被您的 Python 代码(或其他程序)读取。
+
+您可以在 shell 中创建和使用环境变量,而无需使用 Python:
+
+//// tab | Linux、macOS、Windows Bash
+
+
+
+```console
+// 您可以创建一个名为 MY_NAME 的环境变量
+$ export MY_NAME="Wade Wilson"
+
+// 然后您可以与其他程序一起使用它,例如
+$ echo "Hello $MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+// 创建一个名为 MY_NAME 的环境变量
+$ $Env:MY_NAME = "Wade Wilson"
+
+// 与其他程序一起使用它,例如
+$ echo "Hello $Env:MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+### 在 Python 中读取环境变量
+
+您还可以在 Python 之外的地方(例如终端中或使用任何其他方法)创建环境变量,然后在 Python 中读取它们。
+
+例如,您可以有一个名为 `main.py` 的文件,其中包含以下内容:
+
+```Python hl_lines="3"
+import os
+
+name = os.getenv("MY_NAME", "World")
+print(f"Hello {name} from Python")
+```
+
+/// tip
+
+
`os.getenv()` 的第二个参数是要返回的默认值。
+
+如果没有提供默认值,默认为 `None`,此处我们提供了 `"World"` 作为要使用的默认值。
+
+///
+
+然后,您可以调用该 Python 程序:
+
+
+
+```console
+// 这里我们还没有设置环境变量
+$ python main.py
+
+// 因为我们没有设置环境变量,所以我们得到默认值
+
+Hello World from Python
+
+// 但是如果我们先创建一个环境变量
+$ export MY_NAME="Wade Wilson"
+
+// 然后再次调用程序
+$ python main.py
+
+// 现在它可以读取环境变量
+
+Hello Wade Wilson from Python
+```
+
+
+
+由于环境变量可以在代码之外设置,但可以由代码读取,并且不需要与其他文件一起存储(提交到 `git`),因此通常将它们用于配置或设置。
+
+
+
+您还可以仅为特定程序调用创建一个环境变量,该环境变量仅对该程序可用,并且仅在其运行期间有效。
+
+要做到这一点,在程序本身之前的同一行创建它:
+
+
+
+```console
+// 在此程序调用行中创建一个名为 MY_NAME 的环境变量
+$ MY_NAME="Wade Wilson" python main.py
+
+// 现在它可以读取环境变量
+
+Hello Wade Wilson from Python
+
+// 之后环境变量不再存在
+$ python main.py
+
+Hello World from Python
+```
+
+
+
+/// tip
+
+您可以在
Twelve-Factor App: Config 中阅读更多相关信息。
+
+///
+
+### 类型和验证
+
+这些环境变量只能处理文本字符串,因为它们是外部于 Python 的,并且必须与其他程序和整个系统兼容(甚至与不同的操作系统,如 Linux、Windows、macOS)。
+
+这意味着从环境变量中在 Python 中读取的任何值都将是 `str` 类型,任何类型的转换或验证都必须在代码中完成。
+
+## Pydantic 的 `Settings`
+
+幸运的是,Pydantic 提供了一个很好的工具来处理来自环境变量的设置,即
Pydantic: Settings management。
+
+### 创建 `Settings` 对象
+
+从 Pydantic 导入 `BaseSettings` 并创建一个子类,与 Pydantic 模型非常相似。
+
+与 Pydantic 模型一样,您使用类型注释声明类属性,还可以指定默认值。
+
+您可以使用与 Pydantic 模型相同的验证功能和工具,比如不同的数据类型和使用 `Field()` 进行附加验证。
+
+{* ../../docs_src/settings/tutorial001.py hl[2,5:8,11] *}
+
+/// tip
+
+如果您需要一个快速的复制粘贴示例,请不要使用此示例,而应使用下面的最后一个示例。
+
+///
+
+然后,当您创建该 `Settings` 类的实例(在此示例中是 `settings` 对象)时,Pydantic 将以不区分大小写的方式读取环境变量,因此,大写的变量 `APP_NAME` 仍将为属性 `app_name` 读取。
+
+然后,它将转换和验证数据。因此,当您使用该 `settings` 对象时,您将获得您声明的类型的数据(例如 `items_per_user` 将为 `int` 类型)。
+
+### 使用 `settings`
+
+然后,您可以在应用程序中使用新的 `settings` 对象:
+
+{* ../../docs_src/settings/tutorial001.py hl[18:20] *}
+
+### 运行服务器
+
+接下来,您将运行服务器,并将配置作为环境变量传递。例如,您可以设置一个 `ADMIN_EMAIL` 和 `APP_NAME`,如下所示:
+
+
+
+```console
+$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp"uvicorn main:app
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+
+
+/// tip
+
+要为单个命令设置多个环境变量,只需用空格分隔它们,并将它们全部放在命令之前。
+
+///
+
+然后,`admin_email` 设置将为 `"deadpool@example.com"`。
+
+`app_name` 将为 `"ChimichangApp"`。
+
+而 `items_per_user` 将保持其默认值为 `50`。
+
+## 在另一个模块中设置
+
+您可以将这些设置放在另一个模块文件中,就像您在[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}中所见的那样。
+
+例如,您可以创建一个名为 `config.py` 的文件,其中包含以下内容:
+
+{* ../../docs_src/settings/app01/config.py *}
+
+然后在一个名为 `main.py` 的文件中使用它:
+
+{* ../../docs_src/settings/app01/main.py hl[3,11:13] *}
+
+/// tip
+
+您还需要一个名为 `__init__.py` 的文件,就像您在[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}中看到的那样。
+
+///
+
+## 在依赖项中使用设置
+
+在某些情况下,从依赖项中提供设置可能比在所有地方都使用全局对象 `settings` 更有用。
+
+这在测试期间尤其有用,因为很容易用自定义设置覆盖依赖项。
+
+### 配置文件
+
+根据前面的示例,您的 `config.py` 文件可能如下所示:
+
+{* ../../docs_src/settings/app02/config.py hl[10] *}
+
+请注意,现在我们不创建默认实例 `settings = Settings()`。
+
+### 主应用程序文件
+
+现在我们创建一个依赖项,返回一个新的 `config.Settings()`。
+
+{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *}
+
+/// tip
+
+我们稍后会讨论 `@lru_cache`。
+
+目前,您可以将 `get_settings()` 视为普通函数。
+
+///
+
+然后,我们可以将其作为依赖项从“路径操作函数”中引入,并在需要时使用它。
+
+{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *}
+
+### 设置和测试
+
+然后,在测试期间,通过创建 `get_settings` 的依赖项覆盖,很容易提供一个不同的设置对象:
+
+{* ../../docs_src/settings/app02/test_main.py hl[9:10,13,21] *}
+
+在依赖项覆盖中,我们在创建新的 `Settings` 对象时为 `admin_email` 设置了一个新值,然后返回该新对象。
+
+然后,我们可以测试它是否被使用。
+
+## 从 `.env` 文件中读取设置
+
+如果您有许多可能经常更改的设置,可能在不同的环境中,将它们放在一个文件中,然后从该文件中读取它们,就像它们是环境变量一样,可能非常有用。
+
+这种做法相当常见,有一个名称,这些环境变量通常放在一个名为 `.env` 的文件中,该文件被称为“dotenv”。
+
+/// tip
+
+以点 (`.`) 开头的文件是 Unix-like 系统(如 Linux 和 macOS)中的隐藏文件。
+
+但是,dotenv 文件实际上不一定要具有确切的文件名。
+
+///
+
+Pydantic 支持使用外部库从这些类型的文件中读取。您可以在
Pydantic 设置: Dotenv (.env) 支持中阅读更多相关信息。
+
+/// tip
+
+要使其工作,您需要执行 `pip install python-dotenv`。
+
+///
+
+### `.env` 文件
+
+您可以使用以下内容创建一个名为 `.env` 的文件:
+
+```bash
+ADMIN_EMAIL="deadpool@example.com"
+APP_NAME="ChimichangApp"
+```
+
+### 从 `.env` 文件中读取设置
+
+然后,您可以使用以下方式更新您的 `config.py`:
+
+{* ../../docs_src/settings/app03/config.py hl[9:10] *}
+
+在这里,我们在 Pydantic 的 `Settings` 类中创建了一个名为 `Config` 的类,并将 `env_file` 设置为我们想要使用的 dotenv 文件的文件名。
+
+/// tip
+
+`Config` 类仅用于 Pydantic 配置。您可以在
Pydantic Model Config中阅读更多相关信息。
+
+///
+
+### 使用 `lru_cache` 仅创建一次 `Settings`
+
+从磁盘中读取文件通常是一项耗时的(慢)操作,因此您可能希望仅在首次读取后并重复使用相同的设置对象,而不是为每个请求都读取它。
+
+但是,每次执行以下操作:
+
+```Python
+Settings()
+```
+
+都会创建一个新的 `Settings` 对象,并且在创建时会再次读取 `.env` 文件。
+
+如果依赖项函数只是这样的:
+
+```Python
+def get_settings():
+ return Settings()
+```
+
+我们将为每个请求创建该对象,并且将在每个请求中读取 `.env` 文件。 ⚠️
+
+但是,由于我们在顶部使用了 `@lru_cache` 装饰器,因此只有在第一次调用它时,才会创建 `Settings` 对象一次。 ✔️
+
+{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *}
+
+然后,在下一次请求的依赖项中对 `get_settings()` 进行任何后续调用时,它不会执行 `get_settings()` 的内部代码并创建新的 `Settings` 对象,而是返回在第一次调用时返回的相同对象,一次又一次。
+
+#### `lru_cache` 技术细节
+
+`@lru_cache` 修改了它所装饰的函数,以返回第一次返回的相同值,而不是再次计算它,每次都执行函数的代码。
+
+因此,下面的函数将对每个参数组合执行一次。然后,每个参数组合返回的值将在使用完全相同的参数组合调用函数时再次使用。
+
+例如,如果您有一个函数:
+```Python
+@lru_cache
+def say_hi(name: str, salutation: str = "Ms."):
+ return f"Hello {salutation} {name}"
+```
+
+您的程序可以像这样执行:
+
+```mermaid
+sequenceDiagram
+
+participant code as Code
+participant function as say_hi()
+participant execute as Execute function
+
+ rect rgba(0, 255, 0, .1)
+ code ->> function: say_hi(name="Camila")
+ function ->> execute: 执行函数代码
+ execute ->> code: 返回结果
+ end
+
+ rect rgba(0, 255, 255, .1)
+ code ->> function: say_hi(name="Camila")
+ function ->> code: 返回存储的结果
+ end
+
+ rect rgba(0, 255, 0, .1)
+ code ->> function: say_hi(name="Rick")
+ function ->> execute: 执行函数代码
+ execute ->> code: 返回结果
+ end
+
+ rect rgba(0, 255, 0, .1)
+ code ->> function: say_hi(name="Rick", salutation="Mr.")
+ function ->> execute: 执行函数代码
+ execute ->> code: 返回结果
+ end
+
+ rect rgba(0, 255, 255, .1)
+ code ->> function: say_hi(name="Rick")
+ function ->> code: 返回存储的结果
+ end
+
+ rect rgba(0, 255, 255, .1)
+ code ->> function: say_hi(name="Camila")
+ function ->> code: 返回存储的结果
+ end
+```
+
+对于我们的依赖项 `get_settings()`,该函数甚至不接受任何参数,因此它始终返回相同的值。
+
+这样,它的行为几乎就像是一个全局变量。但是由于它使用了依赖项函数,因此我们可以轻松地进行测试时的覆盖。
+
+`@lru_cache` 是 `functools` 的一部分,它是 Python 标准库的一部分,您可以在
Python 文档中了解有关 `@lru_cache` 的更多信息。
+
+## 小结
+
+您可以使用 Pydantic 设置处理应用程序的设置或配置,利用 Pydantic 模型的所有功能。
+
+* 通过使用依赖项,您可以简化测试。
+* 您可以使用 `.env` 文件。
+* 使用 `@lru_cache` 可以避免为每个请求重复读取 dotenv 文件,同时允许您在测试时进行覆盖。
diff --git a/docs/zh/docs/advanced/sub-applications.md b/docs/zh/docs/advanced/sub-applications.md
new file mode 100644
index 000000000..c42be2849
--- /dev/null
+++ b/docs/zh/docs/advanced/sub-applications.md
@@ -0,0 +1,67 @@
+# 子应用 - 挂载
+
+如果需要两个独立的 FastAPI 应用,拥有各自独立的 OpenAPI 与文档,则需设置一个主应用,并**挂载**一个(或多个)子应用。
+
+## 挂载 **FastAPI** 应用
+
+**挂载**是指在特定路径中添加完全**独立**的应用,然后在该路径下使用*路径操作*声明的子应用处理所有事务。
+
+### 顶层应用
+
+首先,创建主(顶层)**FastAPI** 应用及其*路径操作*:
+
+{* ../../docs_src/sub_applications/tutorial001.py hl[3,6:8] *}
+
+### 子应用
+
+接下来,创建子应用及其*路径操作*。
+
+子应用只是另一个标准 FastAPI 应用,但这个应用是被**挂载**的应用:
+
+{* ../../docs_src/sub_applications/tutorial001.py hl[11,14:16] *}
+
+### 挂载子应用
+
+在顶层应用 `app` 中,挂载子应用 `subapi`。
+
+本例的子应用挂载在 `/subapi` 路径下:
+
+{* ../../docs_src/sub_applications/tutorial001.py hl[11,19] *}
+
+### 查看文档
+
+如果主文件是 `main.py`,则用以下 `uvicorn` 命令运行主应用:
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+
+
+查看文档
http://127.0.0.1:8000/docs。
+
+下图显示的是主应用 API 文档,只包括其自有的*路径操作*。
+
+

+
+然后查看子应用文档
http://127.0.0.1:8000/subapi/docs。
+
+下图显示的是子应用的 API 文档,也是只包括其自有的*路径操作*,所有这些路径操作都在 `/subapi` 子路径前缀下。
+
+

+
+两个用户界面都可以正常运行,因为浏览器能够与每个指定的应用或子应用会话。
+
+### 技术细节:`root_path`
+
+以上述方式挂载子应用时,FastAPI 使用 ASGI 规范中的 `root_path` 机制处理挂载子应用路径之间的通信。
+
+这样,子应用就可以为自动文档使用路径前缀。
+
+并且子应用还可以再挂载子应用,一切都会正常运行,FastAPI 可以自动处理所有 `root_path`。
+
+关于 `root_path` 及如何显式使用 `root_path` 的内容,详见[使用代理](behind-a-proxy.md){.internal-link target=_blank}一章。
diff --git a/docs/zh/docs/advanced/templates.md b/docs/zh/docs/advanced/templates.md
new file mode 100644
index 000000000..8b7019ede
--- /dev/null
+++ b/docs/zh/docs/advanced/templates.md
@@ -0,0 +1,125 @@
+# 模板
+
+**FastAPI** 支持多种模板引擎。
+
+Flask 等工具使用的 Jinja2 是最用的模板引擎。
+
+在 Starlette 的支持下,**FastAPI** 应用可以直接使用工具轻易地配置 Jinja2。
+
+## 安装依赖项
+
+安装 `jinja2`:
+
+
+
+```console
+$ pip install jinja2
+
+---> 100%
+```
+
+
+
+## 使用 `Jinja2Templates`
+
+* 导入 `Jinja2Templates`
+* 创建可复用的 `templates` 对象
+* 在返回模板的*路径操作*中声明 `Request` 参数
+* 使用 `templates` 渲染并返回 `TemplateResponse`, 传递模板的名称、request对象以及一个包含多个键值对(用于Jinja2模板)的"context"字典,
+
+{* ../../docs_src/templates/tutorial001.py hl[4,11,15:16] *}
+
+/// note | 笔记
+
+在FastAPI 0.108.0,Starlette 0.29.0之前,`name`是第一个参数。
+并且,在此之前,`request`对象是作为context的一部分以键值对的形式传递的。
+
+///
+
+/// tip | 提示
+
+通过声明 `response_class=HTMLResponse`,API 文档就能识别响应的对象是 HTML。
+
+///
+
+/// note | 技术细节
+
+您还可以使用 `from starlette.templating import Jinja2Templates`。
+
+**FastAPI** 的 `fastapi.templating` 只是为开发者提供的快捷方式。实际上,绝大多数可用响应都直接继承自 Starlette。 `Request` 与 `StaticFiles` 也一样。
+
+///
+
+## 编写模板
+
+编写模板 `templates/item.html`,代码如下:
+
+```jinja hl_lines="7"
+{!../../docs_src/templates/templates/item.html!}
+```
+
+### 模板上下文
+
+在包含如下语句的html中:
+
+{% raw %}
+
+```jinja
+Item ID: {{ id }}
+```
+
+{% endraw %}
+
+...这将显示你从"context"字典传递的 `id`:
+
+```Python
+{"id": id}
+```
+
+例如。当ID为 `42`时, 会渲染成:
+
+```html
+Item ID: 42
+```
+
+### 模板 `url_for` 参数
+
+你还可以在模板内使用 `url_for()`,其参数与*路径操作函数*的参数相同.
+
+所以,该部分:
+
+{% raw %}
+
+```jinja
+
+```
+
+{% endraw %}
+
+...将生成一个与处理*路径操作函数* `read_item(id=id)`的URL相同的链接
+
+例如。当ID为 `42`时, 会渲染成:
+
+```html
+
+```
+
+## 模板与静态文件
+
+你还可以在模板内部将 `url_for()`用于静态文件,例如你挂载的 `name="static"`的 `StaticFiles`。
+
+```jinja hl_lines="4"
+{!../../docs_src/templates/templates/item.html!}
+```
+
+本例中,它将链接到 `static/styles.css`中的CSS文件:
+
+```CSS hl_lines="4"
+{!../../docs_src/templates/static/styles.css!}
+```
+
+因为使用了 `StaticFiles`, **FastAPI** 应用会自动提供位于 URL `/static/styles.css`的 CSS 文件。
+
+## 更多说明
+
+包括测试模板等更多详情,请参阅 Starlette 官方文档 - 模板。
diff --git a/docs/zh/docs/advanced/testing-dependencies.md b/docs/zh/docs/advanced/testing-dependencies.md
new file mode 100644
index 000000000..8d53a6d49
--- /dev/null
+++ b/docs/zh/docs/advanced/testing-dependencies.md
@@ -0,0 +1,53 @@
+# 测试依赖项
+
+## 测试时覆盖依赖项
+
+有些场景下,您可能需要在测试时覆盖依赖项。
+
+即不希望运行原有依赖项(及其子依赖项)。
+
+反之,要在测试期间(或只是为某些特定测试)提供只用于测试的依赖项,并使用此依赖项的值替换原有依赖项的值。
+
+### 用例:外部服务
+
+常见实例是调用外部第三方身份验证应用。
+
+向第三方应用发送令牌,然后返回经验证的用户。
+
+但第三方服务商处理每次请求都可能会收费,并且耗时通常也比调用写死的模拟测试用户更长。
+
+一般只要测试一次外部验证应用就够了,不必每次测试都去调用。
+
+此时,最好覆盖调用外部验证应用的依赖项,使用返回模拟测试用户的自定义依赖项就可以了。
+
+### 使用 `app.dependency_overrides` 属性
+
+对于这些用例,**FastAPI** 应用支持 `app.dependency_overrides` 属性,该属性就是**字典**。
+
+要在测试时覆盖原有依赖项,这个字典的键应当是原依赖项(函数),值是覆盖依赖项(另一个函数)。
+
+这样一来,**FastAPI** 就会调用覆盖依赖项,不再调用原依赖项。
+
+{* ../../docs_src/dependency_testing/tutorial001_an_py310.py hl[26:27,30] *}
+
+/// tip | 提示
+
+**FastAPI** 应用中的任何位置都可以实现覆盖依赖项。
+
+原依赖项可用于*路径操作函数*、*路径操作装饰器*(不需要返回值时)、`.include_router()` 调用等。
+
+FastAPI 可以覆盖这些位置的依赖项。
+
+///
+
+然后,使用 `app.dependency_overrides` 把覆盖依赖项重置为空**字典**:
+
+```Python
+app.dependency_overrides = {}
+```
+
+/// tip | 提示
+
+如果只在某些测试时覆盖依赖项,您可以在测试开始时(在测试函数内)设置覆盖依赖项,并在结束时(在测试函数结尾)重置覆盖依赖项。
+
+///
diff --git a/docs/zh/docs/advanced/testing-events.md b/docs/zh/docs/advanced/testing-events.md
new file mode 100644
index 000000000..71b3739c3
--- /dev/null
+++ b/docs/zh/docs/advanced/testing-events.md
@@ -0,0 +1,5 @@
+# 测试事件:启动 - 关闭
+
+使用 `TestClient` 和 `with` 语句,在测试中运行事件处理器(`startup` 与 `shutdown`)。
+
+{* ../../docs_src/app_testing/tutorial003.py hl[9:12,20:24] *}
diff --git a/docs/zh/docs/advanced/testing-websockets.md b/docs/zh/docs/advanced/testing-websockets.md
new file mode 100644
index 000000000..5d713d5f7
--- /dev/null
+++ b/docs/zh/docs/advanced/testing-websockets.md
@@ -0,0 +1,13 @@
+# 测试 WebSockets
+
+测试 WebSockets 也使用 `TestClient`。
+
+为此,要在 `with` 语句中使用 `TestClient` 连接 WebSocket。
+
+{* ../../docs_src/app_testing/tutorial002.py hl[27:31] *}
+
+/// note | 笔记
+
+更多细节详见
Starlette 官档 - 测试 WebSockets。
+
+///
diff --git a/docs/zh/docs/advanced/using-request-directly.md b/docs/zh/docs/advanced/using-request-directly.md
new file mode 100644
index 000000000..db0fcafdf
--- /dev/null
+++ b/docs/zh/docs/advanced/using-request-directly.md
@@ -0,0 +1,56 @@
+# 直接使用请求
+
+至此,我们已经使用多种类型声明了请求的各种组件。
+
+并从以下对象中提取数据:
+
+* 路径参数
+* 请求头
+* Cookies
+* 等
+
+**FastAPI** 使用这种方式验证数据、转换数据,并自动生成 API 文档。
+
+但有时,我们也需要直接访问 `Request` 对象。
+
+## `Request` 对象的细节
+
+实际上,**FastAPI** 的底层是 **Starlette**,**FastAPI** 只不过是在 **Starlette** 顶层提供了一些工具,所以能直接使用 Starlette 的
`Request` 对象。
+
+但直接从 `Request` 对象提取数据时(例如,读取请求体),**FastAPI** 不会验证、转换和存档数据(为 API 文档使用 OpenAPI)。
+
+不过,仍可以验证、转换与注释(使用 Pydantic 模型的请求体等)其它正常声明的参数。
+
+但在某些特定情况下,还是需要提取 `Request` 对象。
+
+## 直接使用 `Request` 对象
+
+假设要在*路径操作函数*中获取客户端 IP 地址和主机。
+
+此时,需要直接访问请求。
+
+{* ../../docs_src/using_request_directly/tutorial001.py hl[1,7:8] *}
+
+把*路径操作函数*的参数类型声明为 `Request`,**FastAPI** 就能把 `Request` 传递到参数里。
+
+/// tip | 提示
+
+注意,本例除了声明请求参数之外,还声明了路径参数。
+
+因此,能够提取、验证路径参数、并转换为指定类型,还可以用 OpenAPI 注释。
+
+同样,您也可以正常声明其它参数,而且还可以提取 `Request`。
+
+///
+
+## `Request` 文档
+
+更多细节详见
Starlette 官档 - `Request` 对象。
+
+/// note | 技术细节
+
+您也可以使用 `from starlette.requests import Request`。
+
+**FastAPI** 的 `from fastapi import Request` 只是为开发者提供的快捷方式,但其实它直接继承自 Starlette。
+
+///
diff --git a/docs/zh/docs/advanced/websockets.md b/docs/zh/docs/advanced/websockets.md
new file mode 100644
index 000000000..d91aacc03
--- /dev/null
+++ b/docs/zh/docs/advanced/websockets.md
@@ -0,0 +1,176 @@
+# WebSockets
+
+您可以在 **FastAPI** 中使用 [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)。
+
+## 安装 `WebSockets`
+
+首先,您需要安装 `WebSockets`:
+
+```console
+$ pip install websockets
+
+---> 100%
+```
+
+## WebSockets 客户端
+
+### 在生产环境中
+
+在您的生产系统中,您可能使用现代框架(如React、Vue.js或Angular)创建了一个前端。
+
+要使用 WebSockets 与后端进行通信,您可能会使用前端的工具。
+
+或者,您可能有一个原生移动应用程序,直接使用原生代码与 WebSocket 后端通信。
+
+或者,您可能有其他与 WebSocket 终端通信的方式。
+
+---
+
+但是,在本示例中,我们将使用一个非常简单的HTML文档,其中包含一些JavaScript,全部放在一个长字符串中。
+
+当然,这并不是最优的做法,您不应该在生产环境中使用它。
+
+在生产环境中,您应该选择上述任一选项。
+
+但这是一种专注于 WebSockets 的服务器端并提供一个工作示例的最简单方式:
+
+{* ../../docs_src/websockets/tutorial001.py hl[2,6:38,41:43] *}
+
+## 创建 `websocket`
+
+在您的 **FastAPI** 应用程序中,创建一个 `websocket`:
+
+{* ../../docs_src/websockets/tutorial001.py hl[1,46:47] *}
+
+/// note | 技术细节
+
+您也可以使用 `from starlette.websockets import WebSocket`。
+
+**FastAPI** 直接提供了相同的 `WebSocket`,只是为了方便开发人员。但它直接来自 Starlette。
+
+///
+
+## 等待消息并发送消息
+
+在您的 WebSocket 路由中,您可以使用 `await` 等待消息并发送消息。
+
+{* ../../docs_src/websockets/tutorial001.py hl[48:52] *}
+
+您可以接收和发送二进制、文本和 JSON 数据。
+
+## 尝试一下
+
+如果您的文件名为 `main.py`,请使用以下命令运行应用程序:
+
+```console
+$ uvicorn main:app --reload
+
+
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+在浏览器中打开
http://127.0.0.1:8000。
+
+您将看到一个简单的页面,如下所示:
+
+

+
+您可以在输入框中输入消息并发送:
+
+

+
+您的 **FastAPI** 应用程序将回复:
+
+

+
+您可以发送(和接收)多条消息:
+
+

+
+所有这些消息都将使用同一个 WebSocket 连
+
+接。
+
+## 使用 `Depends` 和其他依赖项
+
+在 WebSocket 端点中,您可以从 `fastapi` 导入并使用以下内容:
+
+* `Depends`
+* `Security`
+* `Cookie`
+* `Header`
+* `Path`
+* `Query`
+
+它们的工作方式与其他 FastAPI 端点/ *路径操作* 相同:
+
+{* ../../docs_src/websockets/tutorial002_an_py310.py hl[68:69,82] *}
+
+/// info
+
+由于这是一个 WebSocket,抛出 `HTTPException` 并不是很合理,而是抛出 `WebSocketException`。
+
+您可以使用
规范中定义的有效代码。
+
+///
+
+### 尝试带有依赖项的 WebSockets
+
+如果您的文件名为 `main.py`,请使用以下命令运行应用程序:
+
+```console
+$ uvicorn main:app --reload
+
+
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+在浏览器中打开
http://127.0.0.1:8000。
+
+在页面中,您可以设置:
+
+* "Item ID",用于路径。
+* "Token",作为查询参数。
+
+/// tip
+
+注意,查询参数 `token` 将由依赖项处理。
+
+///
+
+通过这样,您可以连接 WebSocket,然后发送和接收消息:
+
+

+
+## 处理断开连接和多个客户端
+
+当 WebSocket 连接关闭时,`await websocket.receive_text()` 将引发 `WebSocketDisconnect` 异常,您可以捕获并处理该异常,就像本示例中的示例一样。
+
+{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *}
+
+尝试以下操作:
+
+* 使用多个浏览器选项卡打开应用程序。
+* 从这些选项卡中发送消息。
+* 然后关闭其中一个选项卡。
+
+这将引发 `WebSocketDisconnect` 异常,并且所有其他客户端都会收到类似以下的消息:
+
+```
+Client #1596980209979 left the chat
+```
+
+/// tip
+
+上面的应用程序是一个最小和简单的示例,用于演示如何处理和向多个 WebSocket 连接广播消息。
+
+但请记住,由于所有内容都在内存中以单个列表的形式处理,因此它只能在进程运行时工作,并且只能使用单个进程。
+
+如果您需要与 FastAPI 集成更简单但更强大的功能,支持 Redis、PostgreSQL 或其他功能,请查看 [encode/broadcaster](https://github.com/encode/broadcaster)。
+
+///
+
+## 更多信息
+
+要了解更多选项,请查看 Starlette 的文档:
+
+* [WebSocket 类](https://www.starlette.io/websockets/)
+* [基于类的 WebSocket 处理](https://www.starlette.io/endpoints/#websocketendpoint)。
diff --git a/docs/zh/docs/advanced/wsgi.md b/docs/zh/docs/advanced/wsgi.md
new file mode 100644
index 000000000..363025a34
--- /dev/null
+++ b/docs/zh/docs/advanced/wsgi.md
@@ -0,0 +1,35 @@
+# 包含 WSGI - Flask,Django,其它
+
+您可以挂载多个 WSGI 应用,正如您在 [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](behind-a-proxy.md){.internal-link target=_blank} 中所看到的那样。
+
+为此, 您可以使用 `WSGIMiddleware` 来包装你的 WSGI 应用,如:Flask,Django,等等。
+
+## 使用 `WSGIMiddleware`
+
+您需要导入 `WSGIMiddleware`。
+
+然后使用该中间件包装 WSGI 应用(例如 Flask)。
+
+之后将其挂载到某一个路径下。
+
+{* ../../docs_src/wsgi/tutorial001.py hl[2:3,22] *}
+
+## 检查
+
+现在,所有定义在 `/v1/` 路径下的请求将会被 Flask 应用处理。
+
+其余的请求则会被 **FastAPI** 处理。
+
+如果您使用 Uvicorn 运行应用实例并且访问
http://localhost:8000/v1/,您将会看到由 Flask 返回的响应:
+
+```txt
+Hello, World from Flask!
+```
+
+并且如果您访问
http://localhost:8000/v2,您将会看到由 FastAPI 返回的响应:
+
+```JSON
+{
+ "message": "Hello World"
+}
+```
diff --git a/docs/zh/docs/async.md b/docs/zh/docs/async.md
new file mode 100644
index 000000000..9e6962eb1
--- /dev/null
+++ b/docs/zh/docs/async.md
@@ -0,0 +1,444 @@
+# 并发 async / await
+
+有关路径操作函数的 `async def` 语法以及异步代码、并发和并行的一些背景知识。
+
+## 赶时间吗?
+
+
TL;DR:
+
+如果你正在使用第三方库,它们会告诉你使用 `await` 关键字来调用它们,就像这样:
+
+```Python
+results = await some_library()
+```
+
+然后,通过 `async def` 声明你的 *路径操作函数*:
+
+```Python hl_lines="2"
+@app.get('/')
+async def read_results():
+ results = await some_library()
+ return results
+```
+
+/// note
+
+你只能在被 `async def` 创建的函数内使用 `await`
+
+///
+
+---
+
+如果你正在使用一个第三方库和某些组件(比如:数据库、API、文件系统...)进行通信,第三方库又不支持使用 `await` (目前大多数数据库三方库都是这样),这种情况你可以像平常那样使用 `def` 声明一个路径操作函数,就像这样:
+
+```Python hl_lines="2"
+@app.get('/')
+def results():
+ results = some_library()
+ return results
+```
+
+---
+
+如果你的应用程序不需要与其他任何东西通信而等待其响应,请使用 `async def`。
+
+---
+
+如果你不清楚,使用 `def` 就好.
+
+---
+
+**注意**:你可以根据需要在路径操作函数中混合使用 `def` 和 `async def`,并使用最适合你的方式去定义每个函数。FastAPI 将为他们做正确的事情。
+
+无论如何,在上述任何情况下,FastAPI 仍将异步工作,速度也非常快。
+
+但是,通过遵循上述步骤,它将能够进行一些性能优化。
+
+## 技术细节
+
+Python 的现代版本支持通过一种叫**"协程"**——使用 `async` 和 `await` 语法的东西来写**”异步代码“**。
+
+让我们在下面的部分中逐一介绍:
+
+* **异步代码**
+* **`async` 和 `await`**
+* **协程**
+
+## 异步代码
+
+异步代码仅仅意味着编程语言 💬 有办法告诉计算机/程序 🤖 在代码中的某个点,它 🤖 将不得不等待在某些地方完成一些事情。让我们假设一些事情被称为 "慢文件"📝.
+
+所以,在等待"慢文件"📝完成的这段时间,计算机可以做一些其他工作。
+
+然后计算机/程序 🤖 每次有机会都会回来,因为它又在等待,或者它 🤖 完成了当前所有的工作。而且它 🤖 将查看它等待的所有任务中是否有已经完成的,做它必须做的任何事情。
+
+接下来,它 🤖 完成第一个任务(比如是我们的"慢文件"📝) 并继续与之相关的一切。
+
+这个"等待其他事情"通常指的是一些相对较慢(与处理器和 RAM 存储器的速度相比)的
I/O 操作,比如说:
+
+* 通过网络发送来自客户端的数据
+* 客户端接收来自网络中的数据
+* 磁盘中要由系统读取并提供给程序的文件的内容
+* 程序提供给系统的要写入磁盘的内容
+* 一个 API 的远程调用
+* 一个数据库操作,直到完成
+* 一个数据库查询,直到返回结果
+* 等等.
+
+这个执行的时间大多是在等待
I/O 操作,因此它们被叫做 "I/O 密集型" 操作。
+
+它被称为"异步"的原因是因为计算机/程序不必与慢任务"同步",去等待任务完成的确切时刻,而在此期间不做任何事情直到能够获取任务结果才继续工作。
+
+相反,作为一个"异步"系统,一旦完成,任务就可以排队等待一段时间(几微秒),等待计算机程序完成它要做的任何事情,然后回来获取结果并继续处理它们。
+
+对于"同步"(与"异步"相反),他们通常也使用"顺序"一词,因为计算机程序在切换到另一个任务之前是按顺序执行所有步骤,即使这些步骤涉及到等待。
+
+### 并发与汉堡
+
+上述异步代码的思想有时也被称为“并发”,它不同于“并行”。
+
+并发和并行都与“不同的事情或多或少同时发生”有关。
+
+但是并发和并行之间的细节是完全不同的。
+
+要了解差异,请想象以下关于汉堡的故事:
+
+### 并发汉堡
+
+你和你的恋人一起去快餐店,你排队在后面,收银员从你前面的人接单。😍
+
+

+
+然后轮到你了,你为你的恋人和你选了两个非常豪华的汉堡。🍔🍔
+
+

+
+收银员对厨房里的厨师说了一些话,让他们知道他们必须为你准备汉堡(尽管他们目前正在为之前的顾客准备汉堡)。
+
+

+
+你付钱了。 💸
+
+收银员给你轮到的号码。
+
+

+
+当你在等待的时候,你和你的恋人一起去挑选一张桌子,然后你们坐下来聊了很长时间(因为汉堡很豪华,需要一些时间来准备)。
+
+当你和你的恋人坐在桌子旁,等待汉堡的时候,你可以用这段时间来欣赏你的恋人是多么的棒、可爱和聪明✨😍✨。
+
+

+
+在等待中和你的恋人交谈时,你会不时地查看柜台上显示的号码,看看是否已经轮到你了。
+
+然后在某个时刻,终于轮到你了。你去柜台拿汉堡然后回到桌子上。
+
+

+
+你们享用了汉堡,整个过程都很开心。✨
+
+

+
+/// info
+
+漂亮的插画来自
Ketrina Thompson. 🎨
+
+///
+
+---
+
+在那个故事里,假设你是计算机程序 🤖 。
+
+当你在排队时,你只是闲着😴, 轮到你前不做任何事情(仅排队)。但排队很快,因为收银员只接订单(不准备订单),所以这一切都还好。
+
+然后,当轮到你时,需要你做一些实际性的工作,比如查看菜单,决定你想要什么,让你的恋人选择,支付,检查你是否提供了正确的账单或卡,检查你的收费是否正确,检查订单是否有正确的项目,等等。
+
+此时,即使你仍然没有汉堡,你和收银员的工作也"暂停"了⏸, 因为你必须等待一段时间 🕙 让你的汉堡做好。
+
+但是,当你离开柜台并坐在桌子旁,在轮到你的号码前的这段时间,你可以将焦点切换到 🔀 你的恋人上,并做一些"工作"⏯ 🤓。你可以做一些非常"有成效"的事情,比如和你的恋人调情😍.
+
+之后,收银员 💁 把号码显示在显示屏上,并说到 "汉堡做好了",而当显示的号码是你的号码时,你不会立刻疯狂地跳起来。因为你知道没有人会偷你的汉堡,因为你有你的号码,而其他人又有他们自己的号码。
+
+所以你要等待你的恋人完成故事(完成当前的工作⏯ /正在做的事🤓), 轻轻微笑,说你要吃汉堡⏸.
+
+然后你去柜台🔀, 到现在初始任务已经完成⏯, 拿起汉堡,说声谢谢,然后把它们送到桌上。这就完成了与计数器交互的步骤/任务⏹. 这反过来又产生了一项新任务,即"吃汉堡"🔀 ⏯, 上一个"拿汉堡"的任务已经结束了⏹.
+
+### 并行汉堡
+
+现在让我们假设不是"并发汉堡",而是"并行汉堡"。
+
+你和你的恋人一起去吃并行快餐。
+
+你站在队伍中,同时是厨师的几个收银员(比方说8个)从前面的人那里接单。
+
+你之前的每个人都在等待他们的汉堡准备好后才离开柜台,因为8名收银员都会在下一份订单前马上准备好汉堡。
+
+

+
+然后,终于轮到你了,你为你的恋人和你订购了两个非常精美的汉堡。
+
+你付钱了 💸。
+
+

+
+收银员去厨房。
+
+你站在柜台前 🕙等待着,这样就不会有人在你之前抢走你的汉堡,因为没有轮流的号码。
+
+

+
+当你和你的恋人忙于不让任何人出现在你面前,并且在他们到来的时候拿走你的汉堡时,你无法关注到你的恋人。😞
+
+这是"同步"的工作,你被迫与服务员/厨师 👨🍳"同步"。你在此必须等待 🕙 ,在收银员/厨师 👨🍳 完成汉堡并将它们交给你的确切时间到达之前一直等待,否则其他人可能会拿走它们。
+
+

+
+你经过长时间的等待 🕙 ,收银员/厨师 👨🍳终于带着汉堡回到了柜台。
+
+

+
+你拿着汉堡,和你的情人一起上桌。
+
+你们仅仅是吃了它们,就结束了。⏹
+
+

+
+没有太多的交谈或调情,因为大部分时间 🕙 都在柜台前等待😞。
+
+/// info
+
+漂亮的插画来自
Ketrina Thompson. 🎨
+
+///
+
+---
+
+在这个并行汉堡的场景中,你是一个计算机程序 🤖 且有两个处理器(你和你的恋人),都在等待 🕙 ,并投入他们的注意力 ⏯ 在柜台上等待了很长一段时间。
+
+这家快餐店有 8 个处理器(收银员/厨师)。而并发汉堡店可能只有 2 个(一个收银员和一个厨师)。
+
+但最终的体验仍然不是最好的。😞
+
+---
+
+这将是与汉堡的类似故事。🍔
+
+一种更"贴近生活"的例子,想象一家银行。
+
+直到最近,大多数银行都有多个出纳员 👨💼👨💼👨💼👨💼 还有一条长长排队队伍🕙🕙🕙🕙🕙🕙🕙🕙。
+
+所有收银员都是一个接一个的在客户面前做完所有的工作👨💼⏯.
+
+你必须经过 🕙 较长时间排队,否则你就没机会了。
+
+你可不会想带你的恋人 😍 和你一起去银行办事🏦.
+
+### 汉堡结论
+
+在"你与恋人一起吃汉堡"的这个场景中,因为有很多人在等待🕙, 使用并发系统更有意义⏸🔀⏯.
+
+大多数 Web 应用都是这样的。
+
+你的服务器正在等待很多很多用户通过他们不太好的网络发送来的请求。
+
+然后再次等待 🕙 响应回来。
+
+这个"等待" 🕙 是以微秒为单位测量的,但总的来说,最后还是等待很久。
+
+这就是为什么使用异步对于 Web API 很有意义的原因 ⏸🔀⏯。
+
+这种异步机制正是 NodeJS 受到欢迎的原因(尽管 NodeJS 不是并行的),以及 Go 作为编程语言的优势所在。
+
+这与 **FastAPI** 的性能水平相同。
+
+你可以同时拥有并行性和异步性,你可以获得比大多数经过测试的 NodeJS 框架更高的性能,并且与 Go 不相上下, Go 是一种更接近于 C 的编译语言(
全部归功于 Starlette)。
+
+### 并发比并行好吗?
+
+不!这不是故事的本意。
+
+并发不同于并行。而是在需要大量等待的特定场景下效果更好。因此,在 Web 应用程序开发中,它通常比并行要好得多,但这并不意味着全部。
+
+因此,为了平衡这一点,想象一下下面的短篇故事:
+
+> 你必须打扫一个又大又脏的房子。
+
+*是的,这就是完整的故事。*
+
+---
+
+在任何地方, 都不需要等待 🕙 ,只需要在房子的多个地方做着很多工作。
+
+你可以像汉堡的例子那样轮流执行,先是客厅,然后是厨房,但因为你不需要等待 🕙 ,对于任何事情都是清洁,清洁,还是清洁,轮流不会影响任何事情。
+
+无论是否轮流执行(并发),都需要相同的时间来完成,而你也会完成相同的工作量。
+
+但在这种情况下,如果你能带上 8 名前收银员/厨师,现在是清洁工一起清扫,他们中的每一个人(加上你)都能占据房子的一个区域来清扫,你就可以在额外的帮助下并行的更快地完成所有工作。
+
+在这个场景中,每个清洁工(包括你)都将是一个处理器,完成这个工作的一部分。
+
+由于大多数执行时间是由实际工作(而不是等待)占用的,并且计算机中的工作是由
CPU 完成的,所以他们称这些问题为"CPU 密集型"。
+
+---
+
+CPU 密集型操作的常见示例是需要复杂的数学处理。
+
+例如:
+
+* **音频**或**图像**处理;
+* **计算机视觉**: 一幅图像由数百万像素组成,每个像素有3种颜色值,处理通常需要同时对这些像素进行计算;
+* **机器学习**: 它通常需要大量的"矩阵"和"向量"乘法。想象一个包含数字的巨大电子表格,并同时将所有数字相乘;
+* **深度学习**: 这是机器学习的一个子领域,同样适用。只是没有一个数字的电子表格可以相乘,而是一个庞大的数字集合,在很多情况下,你需要使用一个特殊的处理器来构建和使用这些模型。
+
+### 并发 + 并行: Web + 机器学习
+
+使用 **FastAPI**,你可以利用 Web 开发中常见的并发机制的优势(NodeJS 的主要吸引力)。
+
+并且,你也可以利用并行和多进程(让多个进程并行运行)的优点来处理与机器学习系统中类似的 **CPU 密集型** 工作。
+
+这一点,再加上 Python 是**数据科学**、机器学习(尤其是深度学习)的主要语言这一简单事实,使得 **FastAPI** 与数据科学/机器学习 Web API 和应用程序(以及其他许多应用程序)非常匹配。
+
+了解如何在生产环境中实现这种并行性,可查看此文 [Deployment](deployment/index.md){.internal-link target=_blank}。
+
+## `async` 和 `await`
+
+现代版本的 Python 有一种非常直观的方式来定义异步代码。这使它看起来就像正常的"顺序"代码,并在适当的时候"等待"。
+
+当有一个操作需要等待才能给出结果,且支持这个新的 Python 特性时,你可以编写如下代码:
+
+```Python
+burgers = await get_burgers(2)
+```
+
+这里的关键是 `await`。它告诉 Python 它必须等待 ⏸ `get_burgers(2)` 完成它的工作 🕙 ,然后将结果存储在 `burgers` 中。这样,Python 就会知道此时它可以去做其他事情 🔀 ⏯ (比如接收另一个请求)。
+
+要使 `await` 工作,它必须位于支持这种异步机制的函数内。因此,只需使用 `async def` 声明它:
+
+```Python hl_lines="1"
+async def get_burgers(number: int):
+ # Do some asynchronous stuff to create the burgers
+ return burgers
+```
+
+...而不是 `def`:
+
+```Python hl_lines="2"
+# This is not asynchronous
+def get_sequential_burgers(number: int):
+ # Do some sequential stuff to create the burgers
+ return burgers
+```
+
+使用 `async def`,Python 就知道在该函数中,它将遇上 `await`,并且它可以"暂停" ⏸ 执行该函数,直至执行其他操作 🔀 后回来。
+
+当你想调用一个 `async def` 函数时,你必须"等待"它。因此,这不会起作用:
+
+```Python
+# This won't work, because get_burgers was defined with: async def
+burgers = get_burgers(2)
+```
+
+---
+
+因此,如果你使用的库告诉你可以使用 `await` 调用它,则需要使用 `async def` 创建路径操作函数 ,如:
+
+```Python hl_lines="2-3"
+@app.get('/burgers')
+async def read_burgers():
+ burgers = await get_burgers(2)
+ return burgers
+```
+
+### 更多技术细节
+
+你可能已经注意到,`await` 只能在 `async def` 定义的函数内部使用。
+
+但与此同时,必须"等待"通过 `async def` 定义的函数。因此,带 `async def` 的函数也只能在 `async def` 定义的函数内部调用。
+
+那么,这关于先有鸡还是先有蛋的问题,如何调用第一个 `async` 函数?
+
+如果你使用 **FastAPI**,你不必担心这一点,因为"第一个"函数将是你的路径操作函数,FastAPI 将知道如何做正确的事情。
+
+但如果你想在没有 FastAPI 的情况下使用 `async` / `await`,则可以这样做。
+
+### 编写自己的异步代码
+
+Starlette (和 **FastAPI**) 是基于
AnyIO 实现的,这使得它们可以兼容 Python 的标准库
asyncio 和
Trio。
+
+特别是,你可以直接使用
AnyIO 来处理高级的并发用例,这些用例需要在自己的代码中使用更高级的模式。
+
+即使你没有使用 **FastAPI**,你也可以使用
AnyIO 编写自己的异步程序,使其拥有较高的兼容性并获得一些好处(例如, 结构化并发)。
+
+我(指原作者 —— 译者注)基于 AnyIO 新建了一个库,作为一个轻量级的封装层,用来优化类型注解,同时提供了更好的**自动补全**、**内联错误提示**等功能。这个库还附带了一个友好的入门指南和教程,能帮助你**理解**并编写**自己的异步代码**:
Asyncer。如果你有**结合使用异步代码和常规**(阻塞/同步)代码的需求,这个库会特别有用。
+
+### 其他形式的异步代码
+
+这种使用 `async` 和 `await` 的风格在语言中相对较新。
+
+但它使处理异步代码变得容易很多。
+
+这种相同的语法(或几乎相同)最近也包含在现代版本的 JavaScript 中(在浏览器和 NodeJS 中)。
+
+但在此之前,处理异步代码非常复杂和困难。
+
+在以前版本的 Python,你可以使用多线程或者
Gevent。但代码的理解、调试和思考都要复杂许多。
+
+在以前版本的 NodeJS / 浏览器 JavaScript 中,你会使用"回调",因此也可能导致
回调地狱。
+
+## 协程
+
+**协程**只是 `async def` 函数返回的一个非常奇特的东西的称呼。Python 知道它有点像一个函数,它可以启动,也会在某个时刻结束,而且它可能会在内部暂停 ⏸ ,只要内部有一个 `await`。
+
+通过使用 `async` 和 `await` 的异步代码的所有功能大多数被概括为"协程"。它可以与 Go 的主要关键特性 "Goroutines" 相媲美。
+
+## 结论
+
+让我们再来回顾下上文所说的:
+
+> Python 的现代版本可以通过使用 `async` 和 `await` 语法创建**协程**,并用于支持**异步代码**。
+
+现在应该能明白其含义了。✨
+
+所有这些使得 FastAPI(通过 Starlette)如此强大,也是它拥有如此令人印象深刻的性能的原因。
+
+## 非常技术性的细节
+
+/// warning
+
+你可以跳过这里。
+
+这些都是 FastAPI 如何在内部工作的技术细节。
+
+如果你有相当多的技术知识(协程、线程、阻塞等),并且对 FastAPI 如何处理 `async def` 与常规 `def` 感到好奇,请继续。
+
+///
+
+### 路径操作函数
+
+当你使用 `def` 而不是 `async def` 来声明一个*路径操作函数*时,它运行在外部的线程池中并等待其结果,而不是直接调用(因为它会阻塞服务器)。
+
+如果你使用过另一个不以上述方式工作的异步框架,并且你习惯于用普通的 `def` 定义普通的仅计算路径操作函数,以获得微小的性能增益(大约100纳秒),请注意,在 FastAPI 中,效果将完全相反。在这些情况下,最好使用 `async def`,除非路径操作函数内使用执行阻塞
I/O 的代码。
+
+在这两种情况下,与你之前的框架相比,**FastAPI** 可能[仍然很快](index.md#_11){.internal-link target=_blank}。
+
+### 依赖
+
+这同样适用于[依赖](tutorial/dependencies/index.md){.internal-link target=_blank}。如果一个依赖是标准的 `def` 函数而不是 `async def`,它将被运行在外部线程池中。
+
+### 子依赖
+
+你可以拥有多个相互依赖的依赖以及[子依赖](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} (作为函数的参数),它们中的一些可能是通过 `async def` 声明,也可能是通过 `def` 声明。它们仍然可以正常工作,这些通过 `def` 声明的函数将会在外部线程中调用(来自线程池),而不是"被等待"。
+
+### 其他函数
+
+你可直接调用通过 `def` 或 `async def` 创建的任何其他函数,FastAPI 不会影响你调用它们的方式。
+
+这与 FastAPI 为你调用*路径操作函数*和依赖项的逻辑相反。
+
+如果你的函数是通过 `def` 声明的,它将被直接调用(在代码中编写的地方),而不会在线程池中,如果这个函数通过 `async def` 声明,当在代码中调用时,你就应该使用 `await` 等待函数的结果。
+
+---
+
+再次提醒,这些是非常技术性的细节,如果你来搜索它可能对你有用。
+
+否则,你最好应该遵守的指导原则
赶时间吗?.
diff --git a/docs/zh/docs/benchmarks.md b/docs/zh/docs/benchmarks.md
index c133d51b7..71e8d4838 100644
--- a/docs/zh/docs/benchmarks.md
+++ b/docs/zh/docs/benchmarks.md
@@ -1,6 +1,6 @@
# 基准测试
-第三方机构 TechEmpower 的基准测试表明在 Uvicorn 下运行的 **FastAPI** 应用程序是
可用的最快的 Python 框架之一,仅次与 Starlette 和 Uvicorn 本身 (由 FastAPI 内部使用)。(*)
+第三方机构 TechEmpower 的基准测试表明在 Uvicorn 下运行的 **FastAPI** 应用程序是
可用的最快的 Python 框架之一,仅次于 Starlette 和 Uvicorn 本身 (由 FastAPI 内部使用)。(*)
但是在查看基准得分和对比时,请注意以下几点。
@@ -22,7 +22,7 @@
* 具有最佳性能,因为除了服务器本身外,它没有太多额外的代码。
* 您不会直接在 Uvicorn 中编写应用程序。这意味着您的代码至少必须包含 Starlette(或 **FastAPI**)提供的代码。如果您这样做了(即直接在 Uvicorn 中编写应用程序),最终的应用程序会和使用了框架并且最小化了应用代码和 bug 的情况具有相同的性能损耗。
* 如果要对比与 Uvicorn 对标的服务器,请将其与 Daphne,Hypercorn,uWSGI等应用服务器进行比较。
-* **Starlette**:
+* **Starlette**:
* 在 Uvicorn 后使用 Starlette,性能会略有下降。实际上,Starlette 使用 Uvicorn运行。因此,由于必须执行更多的代码,它只会比 Uvicorn 更慢。
* 但它为您提供了构建简单的网络程序的工具,并具有基于路径的路由等功能。
* 如果想对比与 Starlette 对标的开发框架,请将其与 Sanic,Flask,Django 等网络框架(或微框架)进行比较。
diff --git a/docs/zh/docs/contributing.md b/docs/zh/docs/contributing.md
deleted file mode 100644
index 402668c47..000000000
--- a/docs/zh/docs/contributing.md
+++ /dev/null
@@ -1,500 +0,0 @@
-# 开发 - 贡献
-
-首先,你最好先了解 [帮助 FastAPI 及获取帮助](help-fastapi.md){.internal-link target=_blank}的基本方式。
-
-## 开发
-
-如果你已经克隆了源码仓库,并且需要深入研究代码,下面是设置开发环境的指南。
-
-### 通过 `venv` 管理虚拟环境
-
-你可以使用 Python 的 `venv` 模块在一个目录中创建虚拟环境:
-
-
-
-```console
-$ python -m venv env
-```
-
-
-
-这将使用 Python 程序创建一个 `./env/` 目录,然后你将能够为这个隔离的环境安装软件包。
-
-### 激活虚拟环境
-
-使用以下方法激活新环境:
-
-=== "Linux, macOS"
-
-
-
- ```console
- $ source ./env/bin/activate
- ```
-
-
-
-=== "Windows PowerShell"
-
-
-
- ```console
- $ .\env\Scripts\Activate.ps1
- ```
-
-
-
-=== "Windows Bash"
-
- Or if you use Bash for Windows (e.g.
Git Bash):
-
-
-
- ```console
- $ source ./env/Scripts/activate
- ```
-
-
-
-要检查操作是否成功,运行:
-
-=== "Linux, macOS, Windows Bash"
-
-
-
- ```console
- $ which pip
-
- some/directory/fastapi/env/bin/pip
- ```
-
-
-
-=== "Windows PowerShell"
-
-
-
- ```console
- $ Get-Command pip
-
- some/directory/fastapi/env/bin/pip
- ```
-
-
-
-如果显示 `pip` 程序文件位于 `env/bin/pip` 则说明激活成功。 🎉
-
-
-!!! tip
- 每一次你在该环境下使用 `pip` 安装了新软件包时,请再次激活该环境。
-
- 这样可以确保你在使用由该软件包安装的终端程序(如 `flit`)时使用的是当前虚拟环境中的程序,而不是其他的可能是全局安装的程序。
-
-### Flit
-
-**FastAPI** 使用
Flit 来构建、打包和发布项目。
-
-如上所述激活环境后,安装 `flit`:
-
-
-
-```console
-$ pip install flit
-
----> 100%
-```
-
-
-
-现在重新激活环境,以确保你正在使用的是刚刚安装的 `flit`(而不是全局环境的)。
-
-然后使用 `flit` 来安装开发依赖:
-
-=== "Linux, macOS"
-
-
-
- ```console
- $ flit install --deps develop --symlink
-
- ---> 100%
- ```
-
-
-
-=== "Windows"
-
- If you are on Windows, use `--pth-file` instead of `--symlink`:
-
-
-
- ```console
- $ flit install --deps develop --pth-file
-
- ---> 100%
- ```
-
-
-
-这将在虚拟环境中安装所有依赖和本地版本的 FastAPI。
-
-#### 使用本地 FastAPI
-
-如果你创建一个导入并使用 FastAPI 的 Python 文件,然后使用虚拟环境中的 Python 运行它,它将使用你本地的 FastAPI 源码。
-
-并且如果你更改该本地 FastAPI 的源码,由于它是通过 `--symlink` (或 Windows 上的 `--pth-file`)安装的,当你再次运行那个 Python 文件,它将使用你刚刚编辑过的最新版本的 FastAPI。
-
-这样,你不必再去重新"安装"你的本地版本即可测试所有更改。
-
-### 格式化
-
-你可以运行下面的脚本来格式化和清理所有代码:
-
-
-
-```console
-$ bash scripts/format.sh
-```
-
-
-
-它还会自动对所有导入代码进行整理。
-
-为了使整理正确进行,你需要在当前环境中安装本地的 FastAPI,即在运行上述段落中的命令时添加 `--symlink`(或 Windows 上的 `--pth-file`)。
-
-### 格式化导入
-
-还有另一个脚本可以格式化所有导入,并确保你没有未使用的导入代码:
-
-
-
-```console
-$ bash scripts/format-imports.sh
-```
-
-
-
-由于它依次运行了多个命令,并修改和还原了许多文件,所以运行时间会更长一些,因此经常地使用 `scripts/format.sh` 然后仅在提交前执行 `scripts/format-imports.sh` 会更好一些。
-
-## 文档
-
-首先,请确保按上述步骤设置好环境,这将安装所有需要的依赖。
-
-文档使用
MkDocs 生成。
-
-并且在 `./scripts/docs.py` 中还有适用的额外工具/脚本来处理翻译。
-
-!!! tip
- 你不需要去了解 `./scripts/docs.py` 中的代码,只需在命令行中使用它即可。
-
-所有文档均在 `./docs/en/` 目录中以 Markdown 文件格式保存。
-
-许多的教程章节里包含有代码块。
-
-在大多数情况下,这些代码块是可以直接运行的真实完整的应用程序。
-
-实际上,这些代码块不是写在 Markdown 文件内的,它们是位于 `./docs_src/` 目录中的 Python 文件。
-
-生成站点时,这些 Python 文件会被包含/注入到文档中。
-
-### 用于测试的文档
-
-大多数的测试实际上都是针对文档中的示例源文件运行的。
-
-这有助于确保:
-
-* 文档始终是最新的。
-* 文档示例可以直接运行。
-* 绝大多数特性既在文档中得以阐述,又通过测试覆盖进行保障。
-
-在本地开发期间,有一个脚本可以实时重载地构建站点并用来检查所做的任何更改:
-
-
-
-```console
-$ python ./scripts/docs.py live
-
-[INFO] Serving on http://127.0.0.1:8008
-[INFO] Start watching changes
-[INFO] Start detecting changes
-```
-
-
-
-它将在 `http://127.0.0.1:8008` 提供对文档的访问。
-
-这样,你可以编辑文档/源文件并实时查看更改。
-
-#### Typer CLI (可选)
-
-本指引向你展示了如何直接用 `python` 程序运行 `./scripts/docs.py` 中的脚本。
-
-但你也可以使用
Typer CLI,而且在安装了补全功能后,你将可以在终端中对命令进行自动补全。
-
-如果你打算安装 Typer CLI ,可以使用以下命令安装自动补全功能:
-
-
-
-```console
-$ typer --install-completion
-
-zsh completion installed in /home/user/.bashrc.
-Completion will take effect once you restart the terminal.
-```
-
-
-
-### 应用和文档同时运行
-
-如果你使用以下方式运行示例程序:
-
-
-
-```console
-$ uvicorn tutorial001:app --reload
-
-INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
-```
-
-
-
-由于 Uvicorn 默认使用 `8000` 端口 ,因此运行在 `8008` 端口上的文档不会与之冲突。
-
-### 翻译
-
-非常感谢你能够参与文档的翻译!这项工作需要社区的帮助才能完成。 🌎 🚀
-
-以下是参与帮助翻译的步骤。
-
-#### 建议和指南
-
-* 在当前
已有的 pull requests 中查找你使用的语言,添加要求修改或同意合并的评审意见。
-
-!!! tip
- 你可以为已有的 pull requests
添加包含修改建议的评论。
-
- 详情可查看关于
添加 pull request 评审意见 以同意合并或要求修改的文档。
-
-* 在
issues 中查找是否有对你所用语言所进行的协作翻译。
-
-* 每翻译一个页面新增一个 pull request。这将使其他人更容易对其进行评审。
-
-对于我(译注:作者使用西班牙语和英语)不懂的语言,我将在等待其他人评审翻译之后将其合并。
-
-* 你还可以查看是否有你所用语言的翻译,并对其进行评审,这将帮助我了解翻译是否正确以及能否将其合并。
-
-* 使用相同的 Python 示例并且仅翻译文档中的文本。无需进行任何其他更改示例也能正常工作。
-
-* 使用相同的图片、文件名以及链接地址。无需进行任何其他调整来让它们兼容。
-
-* 你可以从
ISO 639-1 代码列表 表中查找你想要翻译语言的两位字母代码。
-
-#### 已有的语言
-
-假设你想将某个页面翻译成已经翻译了一些页面的语言,例如西班牙语。
-
-对于西班牙语来说,它的两位字母代码是 `es`。所以西班牙语翻译的目录位于 `docs/es/`。
-
-!!! tip
- 主要("官方")语言是英语,位于 `docs/en/`目录。
-
-现在为西班牙语文档运行实时服务器:
-
-
-
-```console
-// Use the command "live" and pass the language code as a CLI argument
-$ python ./scripts/docs.py live es
-
-[INFO] Serving on http://127.0.0.1:8008
-[INFO] Start watching changes
-[INFO] Start detecting changes
-```
-
-
-
-现在你可以访问
http://127.0.0.1:8008 实时查看你所做的更改。
-
-如果你查看 FastAPI 的线上文档网站,会看到每种语言都有所有页面。但是某些页面并未被翻译并且会有一处关于缺少翻译的提示。
-
-但是当你像上面这样在本地运行文档时,你只会看到已经翻译的页面。
-
-现在假设你要为 [Features](features.md){.internal-link target=_blank} 章节添加翻译。
-
-* 复制下面的文件:
-
-```
-docs/en/docs/features.md
-```
-
-* 粘贴到你想要翻译语言目录的相同位置,比如:
-
-```
-docs/es/docs/features.md
-```
-
-!!! tip
- 注意路径和文件名的唯一变化是语言代码,从 `en` 更改为 `es`。
-
-* 现在打开位于英语文档目录下的 MkDocs 配置文件:
-
-```
-docs/en/docs/mkdocs.yml
-```
-
-* 在配置文件中找到 `docs/features.md` 所在的位置。结果像这样:
-
-```YAML hl_lines="8"
-site_name: FastAPI
-# More stuff
-nav:
-- FastAPI: index.md
-- Languages:
- - en: /
- - es: /es/
-- features.md
-```
-
-* 打开你正在编辑的语言目录中的 MkDocs 配置文件,例如:
-
-```
-docs/es/docs/mkdocs.yml
-```
-
-* 将其添加到与英语文档完全相同的位置,例如:
-
-```YAML hl_lines="8"
-site_name: FastAPI
-# More stuff
-nav:
-- FastAPI: index.md
-- Languages:
- - en: /
- - es: /es/
-- features.md
-```
-
-如果配置文件中还有其他条目,请确保你所翻译的新条目和它们之间的顺序与英文版本完全相同。
-
-打开浏览器,现在你将看到文档展示了你所加入的新章节。 🎉
-
-现在,你可以将它全部翻译完并在保存文件后进行预览。
-
-#### 新语言
-
-假设你想要为尚未有任何页面被翻译的语言添加翻译。
-
-假设你想要添加克里奥尔语翻译,而且文档中还没有该语言的翻译。
-
-点击上面提到的链接,可以查到"克里奥尔语"的代码为 `ht`。
-
-下一步是运行脚本以生成新的翻译目录:
-
-
-
-```console
-// Use the command new-lang, pass the language code as a CLI argument
-$ python ./scripts/docs.py new-lang ht
-
-Successfully initialized: docs/ht
-Updating ht
-Updating en
-```
-
-
-
-现在,你可以在编辑器中查看新创建的目录 `docs/ht/`。
-
-!!! tip
- 在添加实际的翻译之前,仅以此创建首个 pull request 来设定新语言的配置。
-
- 这样当你在翻译第一个页面时,其他人可以帮助翻译其他页面。🚀
-
-首先翻译文档主页 `docs/ht/index.md`。
-
-然后,你可以根据上面的"已有语言"的指引继续进行翻译。
-
-##### 不支持的新语言
-
-如果在运行实时服务器脚本时收到关于不支持该语言的错误,类似于:
-
-```
- raise TemplateNotFound(template)
-jinja2.exceptions.TemplateNotFound: partials/language/xx.html
-```
-
-这意味着文档的主题不支持该语言(在这种例子中,编造的语言代码是 `xx`)。
-
-但是别担心,你可以将主题语言设置为英语,然后翻译文档的内容。
-
-如果你需要这么做,编辑新语言目录下的 `mkdocs.yml`,它将有类似下面的内容:
-
-```YAML hl_lines="5"
-site_name: FastAPI
-# More stuff
-theme:
- # More stuff
- language: xx
-```
-
-将其中的 language 项从 `xx`(你的语言代码)更改为 `en`。
-
-然后,你就可以再次启动实时服务器了。
-
-#### 预览结果
-
-当你通过 `live` 命令使用 `./scripts/docs.py` 中的脚本时,该脚本仅展示当前语言已有的文件和翻译。
-
-但是当你完成翻译后,你可以像在线上展示一样测试所有内容。
-
-为此,首先构建所有文档:
-
-
-
-```console
-// Use the command "build-all", this will take a bit
-$ python ./scripts/docs.py build-all
-
-Updating es
-Updating en
-Building docs for: en
-Building docs for: es
-Successfully built docs for: es
-Copying en index.md to README.md
-```
-
-
-
-这将在 `./docs_build/` 目录中为每一种语言生成全部的文档。还包括添加所有缺少翻译的文件,并带有一条"此文件还没有翻译"的提醒。但是你不需要对该目录执行任何操作。
-
-然后,它针对每种语言构建独立的 MkDocs 站点,将它们组合在一起,并在 `./site/` 目录中生成最终的输出。
-
-然后你可以使用命令 `serve` 来运行生成的站点:
-
-
-
-```console
-// Use the command "serve" after running "build-all"
-$ python ./scripts/docs.py serve
-
-Warning: this is a very simple server. For development, use mkdocs serve instead.
-This is here only to preview a site with translations already built.
-Make sure you run the build-all command first.
-Serving at: http://127.0.0.1:8008
-```
-
-
-
-## 测试
-
-你可以在本地运行下面的脚本来测试所有代码并生成 HTML 格式的覆盖率报告:
-
-
-
-```console
-$ bash scripts/test-cov-html.sh
-```
-
-
-
-该命令生成了一个 `./htmlcov/` 目录,如果你在浏览器中打开 `./htmlcov/index.html` 文件,你可以交互式地浏览被测试所覆盖的代码区块,并注意是否缺少了任何区块。
diff --git a/docs/zh/docs/deployment/cloud.md b/docs/zh/docs/deployment/cloud.md
new file mode 100644
index 000000000..b086b7b6b
--- /dev/null
+++ b/docs/zh/docs/deployment/cloud.md
@@ -0,0 +1,16 @@
+# 在云上部署 FastAPI
+
+您几乎可以使用**任何云服务商**来部署 FastAPI 应用程序。
+
+在大多数情况下,主要的云服务商都有部署 FastAPI 的指南。
+
+## 云服务商 - 赞助商
+
+一些云服务商 ✨ [**赞助 FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨,这确保了FastAPI 及其**生态系统**持续健康地**发展**。
+
+这表明了他们对 FastAPI 及其**社区**(您)的真正承诺,因为他们不仅想为您提供**良好的服务**,而且还想确保您拥有一个**良好且健康的框架**:FastAPI。 🙇
+
+您可能想尝试他们的服务并阅读他们的指南:
+
+*
Platform.sh
+*
Porter
diff --git a/docs/zh/docs/deployment/concepts.md b/docs/zh/docs/deployment/concepts.md
new file mode 100644
index 000000000..f7208da7c
--- /dev/null
+++ b/docs/zh/docs/deployment/concepts.md
@@ -0,0 +1,330 @@
+# 部署概念
+
+在部署 **FastAPI** 应用程序或任何类型的 Web API 时,有几个概念值得了解,通过掌握这些概念您可以找到**最合适的**方法来**部署您的应用程序**。
+
+一些重要的概念是:
+
+* 安全性 - HTTPS
+* 启动时运行
+* 重新启动
+* 复制(运行的进程数)
+* 内存
+* 开始前的先前步骤
+
+我们接下来了解它们将如何影响**部署**。
+
+我们的最终目标是能够以**安全**的方式**为您的 API 客户端**提供服务,同时要**避免中断**,并且尽可能高效地利用**计算资源**( 例如服务器CPU资源)。 🚀
+
+我将在这里告诉您更多关于这些**概念**的信息,希望能给您提供**直觉**来决定如何在非常不同的环境中部署 API,甚至在是尚不存在的**未来**的环境里。
+
+通过考虑这些概念,您将能够**评估和设计**部署**您自己的 API**的最佳方式。
+
+在接下来的章节中,我将为您提供更多部署 FastAPI 应用程序的**具体方法**。
+
+但现在,让我们仔细看一下这些重要的**概念**。 这些概念也适用于任何其他类型的 Web API。 💡
+
+## 安全性 - HTTPS
+
+在[上一章有关 HTTPS](https.md){.internal-link target=_blank} 中,我们了解了 HTTPS 如何为您的 API 提供加密。
+
+我们还看到,HTTPS 通常由应用程序服务器的**外部**组件(**TLS 终止代理**)提供。
+
+并且必须有某个东西负责**更新 HTTPS 证书**,它可以是相同的组件,也可以是不同的组件。
+
+
+### HTTPS 示例工具
+
+您可以用作 TLS 终止代理的一些工具包括:
+
+* Traefik
+ * 自动处理证书更新 ✨
+* Caddy
+ * 自动处理证书更新 ✨
+* Nginx
+ * 使用 Certbot 等外部组件进行证书更新
+* HAProxy
+ * 使用 Certbot 等外部组件进行证书更新
+* 带有 Ingress Controller(如Nginx) 的 Kubernetes
+ * 使用诸如 cert-manager 之类的外部组件来进行证书更新
+* 由云服务商内部处理,作为其服务的一部分(请阅读下文👇)
+
+另一种选择是您可以使用**云服务**来完成更多工作,包括设置 HTTPS。 它可能有一些限制或向您收取更多费用等。但在这种情况下,您不必自己设置 TLS 终止代理。
+
+我将在接下来的章节中向您展示一些具体示例。
+
+---
+
+接下来要考虑的概念都是关于运行实际 API 的程序(例如 Uvicorn)。
+
+## 程序和进程
+
+我们将讨论很多关于正在运行的“**进程**”的内容,因此弄清楚它的含义以及与“**程序**”这个词有什么区别是很有用的。
+
+### 什么是程序
+
+**程序**这个词通常用来描述很多东西:
+
+* 您编写的 **代码**,**Python 文件**。
+* 操作系统可以**执行**的**文件**,例如:`python`、`python.exe`或`uvicorn`。
+* 在操作系统上**运行**、使用CPU 并将内容存储在内存上的特定程序。 这也被称为**进程**。
+
+### 什么是进程
+
+**进程** 这个词通常以更具体的方式使用,仅指在操作系统中运行的东西(如上面的最后一点):
+
+* 在操作系统上**运行**的特定程序。
+ * 这不是指文件,也不是指代码,它**具体**指的是操作系统正在**执行**和管理的东西。
+* 任何程序,任何代码,**只有在执行时才能做事**。 因此,是当有**进程正在运行**时。
+* 该进程可以由您或操作系统**终止**(或“杀死”)。 那时,它停止运行/被执行,并且它可以**不再做事情**。
+* 您计算机上运行的每个应用程序背后都有一些进程,每个正在运行的程序,每个窗口等。并且通常在计算机打开时**同时**运行许多进程。
+* **同一程序**可以有**多个进程**同时运行。
+
+如果您检查操作系统中的“任务管理器”或“系统监视器”(或类似工具),您将能够看到许多正在运行的进程。
+
+例如,您可能会看到有多个进程运行同一个浏览器程序(Firefox、Chrome、Edge 等)。 他们通常每个tab运行一个进程,再加上一些其他额外的进程。
+
+

+
+---
+
+现在我们知道了术语“进程”和“程序”之间的区别,让我们继续讨论部署。
+
+## 启动时运行
+
+在大多数情况下,当您创建 Web API 时,您希望它**始终运行**、不间断,以便您的客户端始终可以访问它。 这是当然的,除非您有特定原因希望它仅在某些情况下运行,但大多数时候您希望它不断运行并且**可用**。
+
+### 在远程服务器中
+
+当您设置远程服务器(云服务器、虚拟机等)时,您可以做的最简单的事情就是手动运行 Uvicorn(或类似的),就像本地开发时一样。
+
+它将会在**开发过程中**发挥作用并发挥作用。
+
+但是,如果您与服务器的连接丢失,**正在运行的进程**可能会终止。
+
+如果服务器重新启动(例如更新后或从云提供商迁移后),您可能**不会注意到它**。 因此,您甚至不知道必须手动重新启动该进程。 所以,你的 API 将一直处于挂掉的状态。 😱
+
+
+### 启动时自动运行
+
+一般来说,您可能希望服务器程序(例如 Uvicorn)在服务器启动时自动启动,并且不需要任何**人为干预**,让进程始终与您的 API 一起运行(例如 Uvicorn 运行您的 FastAPI 应用程序) 。
+
+### 单独的程序
+
+为了实现这一点,您通常会有一个**单独的程序**来确保您的应用程序在启动时运行。 在许多情况下,它还可以确保其他组件或应用程序也运行,例如数据库。
+
+### 启动时运行的示例工具
+
+可以完成这项工作的工具的一些示例是:
+
+* Docker
+* Kubernetes
+* Docker Compose
+* Docker in Swarm Mode
+* Systemd
+* Supervisor
+* 作为其服务的一部分由云提供商内部处理
+* 其他的...
+
+我将在接下来的章节中为您提供更具体的示例。
+
+
+## 重新启动
+
+与确保应用程序在启动时运行类似,您可能还想确保它在挂掉后**重新启动**。
+
+### 我们会犯错误
+
+作为人类,我们总是会犯**错误**。 软件几乎*总是*在不同的地方隐藏着**bug**。 🐛
+
+作为开发人员,当我们发现这些bug并实现新功能(也可能添加新bug😅)时,我们会不断改进代码。
+
+### 自动处理小错误
+
+使用 FastAPI 构建 Web API 时,如果我们的代码中存在错误,FastAPI 通常会将其包含到触发错误的单个请求中。 🛡
+
+对于该请求,客户端将收到 **500 内部服务器错误**,但应用程序将继续处理下一个请求,而不是完全崩溃。
+
+### 更大的错误 - 崩溃
+
+尽管如此,在某些情况下,我们编写的一些代码可能会导致整个应用程序崩溃,从而导致 Uvicorn 和 Python 崩溃。 💥
+
+尽管如此,您可能不希望应用程序因为某个地方出现错误而保持死机状态,您可能希望它**继续运行**,至少对于未破坏的*路径操作*。
+
+### 崩溃后重新启动
+
+但在那些严重错误导致正在运行的**进程**崩溃的情况下,您需要一个外部组件来负责**重新启动**进程,至少尝试几次......
+
+/// tip
+
+...尽管如果整个应用程序只是**立即崩溃**,那么永远重新启动它可能没有意义。 但在这些情况下,您可能会在开发过程中注意到它,或者至少在部署后立即注意到它。
+
+ 因此,让我们关注主要情况,在**未来**的某些特定情况下,它可能会完全崩溃,但重新启动它仍然有意义。
+
+///
+
+您可能希望让这个东西作为 **外部组件** 负责重新启动您的应用程序,因为到那时,使用 Uvicorn 和 Python 的同一应用程序已经崩溃了,因此同一应用程序的相同代码中没有东西可以对此做出什么。
+
+### 自动重新启动的示例工具
+
+在大多数情况下,用于**启动时运行程序**的同一工具也用于处理自动**重新启动**。
+
+例如,可以通过以下方式处理:
+
+* Docker
+* Kubernetes
+* Docker Compose
+* Docker in Swarm mode
+* Systemd
+* Supervisor
+* 作为其服务的一部分由云提供商内部处理
+* 其他的...
+
+## 复制 - 进程和内存
+
+对于 FastAPI 应用程序,使用像 Uvicorn 这样的服务器程序,在**一个进程**中运行一次就可以同时为多个客户端提供服务。
+
+但在许多情况下,您会希望同时运行多个工作进程。
+
+### 多进程 - Workers
+
+如果您的客户端数量多于单个进程可以处理的数量(例如,如果虚拟机不是太大),并且服务器的 CPU 中有 **多个核心**,那么您可以让 **多个进程** 运行 同时处理同一个应用程序,并在它们之间分发所有请求。
+
+当您运行同一 API 程序的**多个进程**时,它们通常称为 **workers**。
+
+### 工作进程和端口
+
+还记得文档 [About HTTPS](https.md){.internal-link target=_blank} 中只有一个进程可以侦听服务器中的端口和 IP 地址的一种组合吗?
+
+现在仍然是对的。
+
+因此,为了能够同时拥有**多个进程**,必须有一个**单个进程侦听端口**,然后以某种方式将通信传输到每个工作进程。
+
+### 每个进程的内存
+
+现在,当程序将内容加载到内存中时,例如,将机器学习模型加载到变量中,或者将大文件的内容加载到变量中,所有这些都会消耗服务器的一点内存 (RAM) 。
+
+多个进程通常**不共享任何内存**。 这意味着每个正在运行的进程都有自己的东西、变量和内存。 如果您的代码消耗了大量内存,**每个进程**将消耗等量的内存。
+
+### 服务器内存
+
+例如,如果您的代码加载 **1 GB 大小**的机器学习模型,则当您使用 API 运行一个进程时,它将至少消耗 1 GB RAM。 如果您启动 **4 个进程**(4 个工作进程),每个进程将消耗 1 GB RAM。 因此,您的 API 总共将消耗 **4 GB RAM**。
+
+如果您的远程服务器或虚拟机只有 3 GB RAM,尝试加载超过 4 GB RAM 将导致问题。 🚨
+
+
+### 多进程 - 一个例子
+
+在此示例中,有一个 **Manager Process** 启动并控制两个 **Worker Processes**。
+
+该管理器进程可能是监听 IP 中的 **端口** 的进程。 它将所有通信传输到工作进程。
+
+这些工作进程将是运行您的应用程序的进程,它们将执行主要计算以接收 **请求** 并返回 **响应**,并且它们将加载您放入 RAM 中的变量中的任何内容。
+
+

+
+当然,除了您的应用程序之外,同一台机器可能还运行**其他进程**。
+
+一个有趣的细节是,随着时间的推移,每个进程使用的 **CPU 百分比可能会发生很大变化,但内存 (RAM) 通常会或多或少保持稳定**。
+
+如果您有一个每次执行相当数量的计算的 API,并且您有很多客户端,那么 **CPU 利用率** 可能也会保持稳定(而不是不断快速上升和下降)。
+
+### 复制工具和策略示例
+
+可以通过多种方法来实现这一目标,我将在接下来的章节中向您详细介绍具体策略,例如在谈论 Docker 和容器时。
+
+要考虑的主要限制是必须有一个**单个**组件来处理**公共IP**中的**端口**。 然后它必须有一种方法将通信**传输**到复制的**进程/worker**。
+
+以下是一些可能的组合和策略:
+
+* **Gunicorn** 管理 **Uvicorn workers**
+ * Gunicorn 将是监听 **IP** 和 **端口** 的 **进程管理器**,复制将通过 **多个 Uvicorn 工作进程** 进行
+* **Uvicorn** 管理 **Uvicorn workers**
+ * 一个 Uvicorn **进程管理器** 将监听 **IP** 和 **端口**,并且它将启动 **多个 Uvicorn 工作进程**
+* **Kubernetes** 和其他分布式 **容器系统**
+ * **Kubernetes** 层中的某些东西将侦听 **IP** 和 **端口**。 复制将通过拥有**多个容器**,每个容器运行**一个 Uvicorn 进程**
+* **云服务** 为您处理此问题
+ * 云服务可能**为您处理复制**。 它可能会让您定义 **要运行的进程**,或要使用的 **容器映像**,在任何情况下,它很可能是 **单个 Uvicorn 进程**,并且云服务将负责复制它。
+
+
+
+/// tip
+
+如果这些关于 **容器**、Docker 或 Kubernetes 的内容还没有多大意义,请不要担心。
+
+ 我将在以后的章节中向您详细介绍容器镜像、Docker、Kubernetes 等:[容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank}。
+
+///
+
+## 启动之前的步骤
+
+在很多情况下,您希望在**启动**应用程序之前执行一些步骤。
+
+例如,您可能想要运行**数据库迁移**。
+
+但在大多数情况下,您只想执行这些步骤**一次**。
+
+因此,在启动应用程序之前,您将需要一个**单个进程**来执行这些**前面的步骤**。
+
+而且您必须确保它是运行前面步骤的单个进程, *即使*之后您为应用程序本身启动**多个进程**(多个worker)。 如果这些步骤由**多个进程**运行,它们会通过在**并行**运行来**重复**工作,并且如果这些步骤像数据库迁移一样需要小心处理,它们可能会导致每个进程和其他进程发生冲突。
+
+当然,也有一些情况,多次运行前面的步骤也没有问题,这样的话就好办多了。
+
+/// tip
+
+另外,请记住,根据您的设置,在某些情况下,您在开始应用程序之前**可能甚至不需要任何先前的步骤**。
+
+ 在这种情况下,您就不必担心这些。 🤷
+
+///
+
+### 前面步骤策略的示例
+
+这将在**很大程度上取决于您部署系统的方式**,并且可能与您启动程序、处理重启等的方式有关。
+
+以下是一些可能的想法:
+
+* Kubernetes 中的“Init Container”在应用程序容器之前运行
+* 一个 bash 脚本,运行前面的步骤,然后启动您的应用程序
+ * 您仍然需要一种方法来启动/重新启动 bash 脚本、检测错误等。
+
+/// tip
+
+我将在以后的章节中为您提供使用容器执行此操作的更具体示例:[容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank}。
+
+///
+
+## 资源利用率
+
+您的服务器是一个**资源**,您可以通过您的程序消耗或**利用**CPU 上的计算时间以及可用的 RAM 内存。
+
+您想要消耗/利用多少系统资源? 您可能很容易认为“不多”,但实际上,您可能希望在不崩溃的情况下**尽可能多地消耗**。
+
+如果您支付了 3 台服务器的费用,但只使用了它们的一点点 RAM 和 CPU,那么您可能**浪费金钱** 💸,并且可能 **浪费服务器电力** 🌎,等等。
+
+在这种情况下,最好只拥有 2 台服务器并使用更高比例的资源(CPU、内存、磁盘、网络带宽等)。
+
+另一方面,如果您有 2 台服务器,并且正在使用 **100% 的 CPU 和 RAM**,则在某些时候,一个进程会要求更多内存,并且服务器将不得不使用磁盘作为“内存” (这可能会慢数千倍),甚至**崩溃**。 或者一个进程可能需要执行一些计算,并且必须等到 CPU 再次空闲。
+
+在这种情况下,最好购买**一台额外的服务器**并在其上运行一些进程,以便它们都有**足够的 RAM 和 CPU 时间**。
+
+由于某种原因,您的 API 的使用量也有可能出现**激增**。 也许它像病毒一样传播开来,或者也许其他一些服务或机器人开始使用它。 在这些情况下,您可能需要额外的资源来保证安全。
+
+您可以将一个**任意数字**设置为目标,例如,资源利用率**在 50% 到 90%** 之间。 重点是,这些可能是您想要衡量和用来调整部署的主要内容。
+
+您可以使用“htop”等简单工具来查看服务器中使用的 CPU 和 RAM 或每个进程使用的数量。 或者您可以使用更复杂的监控工具,这些工具可能分布在服务器等上。
+
+
+## 回顾
+
+您在这里阅读了一些在决定如何部署应用程序时可能需要牢记的主要概念:
+
+* 安全性 - HTTPS
+* 启动时运行
+* 重新启动
+* 复制(运行的进程数)
+* 内存
+* 开始前的先前步骤
+
+了解这些想法以及如何应用它们应该会给您足够的直觉在配置和调整部署时做出任何决定。 🤓
+
+在接下来的部分中,我将为您提供更具体的示例,说明您可以遵循的可能策略。 🚀
diff --git a/docs/zh/docs/deployment/docker.md b/docs/zh/docs/deployment/docker.md
new file mode 100644
index 000000000..f120ebfb8
--- /dev/null
+++ b/docs/zh/docs/deployment/docker.md
@@ -0,0 +1,760 @@
+# 容器中的 FastAPI - Docker
+
+部署 FastAPI 应用程序时,常见的方法是构建 **Linux 容器镜像**。 通常使用
**Docker** 完成。 然后,你可以通过几种可能的方式之一部署该容器镜像。
+
+使用 Linux 容器有几个优点,包括**安全性**、**可复制性**、**简单性**等。
+
+/// tip
+
+赶时间并且已经知道这些东西了? 跳转到下面的 [`Dockerfile` 👇](#fastapi-docker_1)。
+
+///
+
+
+Dockerfile Preview 👀
+
+```Dockerfile
+FROM python:3.9
+
+WORKDIR /code
+
+COPY ./requirements.txt /code/requirements.txt
+
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+
+COPY ./app /code/app
+
+CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
+
+# If running behind a proxy like Nginx or Traefik add --proxy-headers
+# CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--proxy-headers"]
+```
+
+
+
+## 什么是容器
+
+容器(主要是 Linux 容器)是一种非常**轻量级**的打包应用程序的方式,其包括所有依赖项和必要的文件,同时它们可以和同一系统中的其他容器(或者其他应用程序/组件)相互隔离。
+
+Linux 容器使用宿主机(如物理服务器、虚拟机、云服务器等)的Linux 内核运行。 这意味着它们非常轻量(与模拟整个操作系统的完整虚拟机相比)。
+
+通过这样的方式,容器消耗**很少的资源**,与直接运行进程相当(虚拟机会消耗更多)。
+
+容器的进程(通常只有一个)、文件系统和网络都运行在隔离的环境,这简化了部署、安全、开发等。
+
+## 什么是容器镜像
+
+**容器**是从**容器镜像**运行的。
+
+容器镜像是容器中文件、环境变量和默认命令/程序的**静态**版本。 **静态**这里的意思是容器**镜像**还没有运行,只是打包的文件和元数据。
+
+与存储静态内容的“**容器镜像**”相反,“**容器**”通常指正在运行的实例,即正在**执行的**。
+
+当**容器**启动并运行时(从**容器镜像**启动),它可以创建或更改文件、环境变量等。这些更改将仅存在于该容器中,而不会持久化到底层的容器镜像中(不会保存到磁盘)。
+
+容器镜像相当于**程序**和文件,例如 `python`命令 和某些文件 如`main.py`。
+
+而**容器**本身(与**容器镜像**相反)是镜像的实际运行实例,相当于**进程**。 事实上,容器仅在有**进程运行**时才运行(通常它只是一个单独的进程)。 当容器中没有进程运行时,容器就会停止。
+
+
+
+## 容器镜像
+
+Docker 一直是创建和管理**容器镜像**和**容器**的主要工具之一。
+
+还有一个公共
Docker Hub ,其中包含预制的 **官方容器镜像**, 适用于许多工具、环境、数据库和应用程序。
+
+例如,有一个官方的
Python 镜像。
+
+还有许多其他镜像用于不同的需要(例如数据库),例如:
+
+
+*
PostgreSQL
+*
MySQL
+*
MongoDB
+*
Redis, etc.
+
+
+通过使用预制的容器镜像,可以非常轻松地**组合**并使用不同的工具。 例如,尝试一个新的数据库。 在大多数情况下,你可以使用**官方镜像**,只需为其配置环境变量即可。
+
+这样,在许多情况下,你可以了解容器和 Docker,并通过许多不同的工具和组件重复使用这些知识。
+
+因此,你可以运行带有不同内容的**多个容器**,例如数据库、Python 应用程序、带有 React 前端应用程序的 Web 服务器,并通过内部网络将它们连接在一起。
+
+所有容器管理系统(如 Docker 或 Kubernetes)都集成了这些网络功能。
+
+## 容器和进程
+
+**容器镜像**通常在其元数据中包含启动**容器**时应运行的默认程序或命令以及要传递给该程序的参数。 与在命令行中的情况非常相似。
+
+当 **容器** 启动时,它将运行该命令/程序(尽管你可以覆盖它并使其运行不同的命令/程序)。
+
+只要**主进程**(命令或程序)在运行,容器就在运行。
+
+容器通常有一个**单个进程**,但也可以从主进程启动子进程,这样你就可以在同一个容器中拥有**多个进程**。
+
+但是,如果没有**至少一个正在运行的进程**,就不可能有一个正在运行的容器。 如果主进程停止,容器也会停止。
+
+
+## 为 FastAPI 构建 Docker 镜像
+
+好吧,让我们现在构建一些东西! 🚀
+
+我将向你展示如何基于 **官方 Python** 镜像 **从头开始** 为 FastAPI 构建 **Docker 镜像**。
+
+这是你在**大多数情况**下想要做的,例如:
+
+* 使用 **Kubernetes** 或类似工具
+* 在 **Raspberry Pi** 上运行时
+* 使用可为你运行容器镜像的云服务等。
+
+### 依赖项
+
+你通常会在某个文件中包含应用程序的**依赖项**。
+
+具体做法取决于你**安装**这些依赖时所使用的工具。
+
+最常见的方法是创建一个`requirements.txt`文件,其中每行包含一个包名称和它的版本。
+
+你当然也可以使用在[关于 FastAPI 版本](versions.md){.internal-link target=_blank} 中讲到的方法来设置版本范围。
+
+例如,你的`requirements.txt`可能如下所示:
+
+
+```
+fastapi>=0.68.0,<0.69.0
+pydantic>=1.8.0,<2.0.0
+uvicorn>=0.15.0,<0.16.0
+```
+
+你通常会使用`pip`安装这些依赖项:
+
+
+
+```console
+$ pip install -r requirements.txt
+---> 100%
+Successfully installed fastapi pydantic uvicorn
+```
+
+
+
+/// info
+
+还有其他文件格式和工具来定义和安装依赖项。
+
+ 我将在下面的部分中向你展示一个使用 Poetry 的示例。 👇
+
+///
+
+### 创建 **FastAPI** 代码
+
+* 创建`app`目录并进入。
+* 创建一个空文件`__init__.py`。
+* 创建一个 `main.py` 文件:
+
+
+
+```Python
+from typing import Union
+
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+def read_root():
+ return {"Hello": "World"}
+
+
+@app.get("/items/{item_id}")
+def read_item(item_id: int, q: Union[str, None] = None):
+ return {"item_id": item_id, "q": q}
+```
+
+### Dockerfile
+
+现在在相同的project目录创建一个名为`Dockerfile`的文件:
+
+```{ .dockerfile .annotate }
+# (1)
+FROM python:3.9
+
+# (2)
+WORKDIR /code
+
+# (3)
+COPY ./requirements.txt /code/requirements.txt
+
+# (4)
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+
+# (5)
+COPY ./app /code/app
+
+# (6)
+CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
+```
+
+1. 从官方Python基础镜像开始。
+
+2. 将当前工作目录设置为`/code`。
+
+ 这是我们放置`requirements.txt`文件和`app`目录的位置。
+
+3. 将符合要求的文件复制到`/code`目录中。
+
+ 首先仅复制requirements.txt文件,而不复制其余代码。
+
+ 由于此文件**不经常更改**,Docker 将检测到它并在这一步中使用**缓存**,从而为下一步启用缓存。
+
+4. 安装需求文件中的包依赖项。
+
+ `--no-cache-dir` 选项告诉 `pip` 不要在本地保存下载的包,因为只有当 `pip` 再次运行以安装相同的包时才会这样,但在与容器一起工作时情况并非如此。
+
+ /// note | 笔记
+
+ `--no-cache-dir` 仅与 `pip` 相关,与 Docker 或容器无关。
+
+ ///
+
+ `--upgrade` 选项告诉 `pip` 升级软件包(如果已经安装)。
+
+ 因为上一步复制文件可以被 **Docker 缓存** 检测到,所以此步骤也将 **使用 Docker 缓存**(如果可用)。
+
+ 在开发过程中一次又一次构建镜像时,在此步骤中使用缓存将为你节省大量**时间**,而不是**每次**都**下载和安装**所有依赖项。
+
+
+5. 将“./app”目录复制到“/code”目录中。
+
+ 由于其中包含**更改最频繁**的所有代码,因此 Docker **缓存**不会轻易用于此操作或任何**后续步骤**。
+
+ 因此,将其放在`Dockerfile`**接近最后**的位置非常重要,以优化容器镜像的构建时间。
+
+6. 设置**命令**来运行 `uvicorn` 服务器。
+
+ `CMD` 接受一个字符串列表,每个字符串都是你在命令行中输入的内容,并用空格分隔。
+
+ 该命令将从 **当前工作目录** 运行,即你上面使用`WORKDIR /code`设置的同一`/code`目录。
+
+ 因为程序将从`/code`启动,并且其中包含你的代码的目录`./app`,所以**Uvicorn**将能够从`app.main`中查看并**import**`app`。
+
+/// tip
+
+通过单击代码中的每个数字气泡来查看每行的作用。 👆
+
+///
+
+你现在应该具有如下目录结构:
+```
+.
+├── app
+│ ├── __init__.py
+│ └── main.py
+├── Dockerfile
+└── requirements.txt
+```
+
+
+#### 在 TLS 终止代理后面
+
+如果你在 Nginx 或 Traefik 等 TLS 终止代理(负载均衡器)后面运行容器,请添加选项 `--proxy-headers`,这将告诉 Uvicorn 信任该代理发送的标头,告诉它应用程序正在 HTTPS 后面运行等信息
+
+```Dockerfile
+CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
+```
+
+#### Docker 缓存
+
+这个`Dockerfile`中有一个重要的技巧,我们首先只单独复制**包含依赖项的文件**,而不是其余代码。 让我来告诉你这是为什么。
+
+```Dockerfile
+COPY ./requirements.txt /code/requirements.txt
+```
+
+Docker之类的构建工具是通过**增量**的方式来构建这些容器镜像的。具体做法是从`Dockerfile`顶部开始,每一条指令生成的文件都是镜像的“一层”,同过把这些“层”一层一层地叠加到基础镜像上,最后我们就得到了最终的镜像。
+
+Docker 和类似工具在构建镜像时也会使用**内部缓存**,如果自上次构建容器镜像以来文件没有更改,那么它将**重新使用上次创建的同一层**,而不是再次复制文件并从头开始创建新层。
+
+仅仅避免文件的复制不一定会有太多速度提升,但是如果在这一步使用了缓存,那么才可以**在下一步中使用缓存**。 例如,可以使用安装依赖项那条指令的缓存:
+
+```Dockerfile
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+```
+
+
+包含包依赖项的文件**不会频繁更改**。 只复制该文件(不复制其他的应用代码),Docker 才能在这一步**使用缓存**。
+
+Docker 进而能**使用缓存进行下一步**,即下载并安装这些依赖项。 这才是我们**节省大量时间**的地方。 ✨ ...可以避免无聊的等待。 😪😆
+
+下载和安装依赖项**可能需要几分钟**,但使用**缓存**最多**只需要几秒钟**。
+
+由于你在开发过程中会一次又一次地构建容器镜像以检查代码更改是否有效,因此可以累计节省大量时间。
+
+在`Dockerfile`末尾附近,我们再添加复制代码的指令。 由于代码是**更改最频繁的**,所以将其放在最后,因为这一步之后的内容基本上都是无法使用缓存的。
+
+```Dockerfile
+COPY ./app /code/app
+```
+
+### 构建 Docker 镜像
+
+现在所有文件都已就位,让我们构建容器镜像。
+
+* 转到项目目录(在`Dockerfile`所在的位置,包含`app`目录)。
+* 构建你的 FastAPI 镜像:
+
+
+
+
+```console
+$ docker build -t myimage .
+
+---> 100%
+```
+
+
+
+
+/// tip
+
+注意最后的 `.`,它相当于`./`,它告诉 Docker 用于构建容器镜像的目录。
+
+在本例中,它是相同的当前目录(`.`)。
+
+///
+
+### 启动 Docker 容器
+
+* 根据你的镜像运行容器:
+
+
+
+```console
+$ docker run -d --name mycontainer -p 80:80 myimage
+```
+
+
+
+## 检查一下
+
+
+你应该能在Docker容器的URL中检查它,例如:
http://192.168.99.100/items/5?q=somequery 或
http://127.0.0.1/items/5?q=somequery (或其他等价的,使用 Docker 主机).
+
+你会看到类似内容:
+
+```JSON
+{"item_id": 5, "q": "somequery"}
+```
+
+## 交互式 API 文档
+
+现在你可以转到
http://192.168.99.100/docs 或
http://127.0.0.1/docs (或其他等价的,使用 Docker 主机)。
+
+你将看到自动交互式 API 文档(由
Swagger UI):
+
+
+
+## 备选的 API 文档
+
+你还可以访问
http://192.168.99.100/redoc 或
http://127.0.0.1/redoc (或其他等价的,使用 Docker 主机)。
+
+你将看到备选的自动文档(由
ReDoc 提供):
+
+
+
+## 使用单文件 FastAPI 构建 Docker 镜像
+
+如果你的 FastAPI 是单个文件,例如没有`./app`目录的`main.py`,则你的文件结构可能如下所示:
+
+```
+.
+├── Dockerfile
+├── main.py
+└── requirements.txt
+```
+
+然后你只需更改相应的路径即可将文件复制到`Dockerfile`中:
+
+```{ .dockerfile .annotate hl_lines="10 13" }
+FROM python:3.9
+
+WORKDIR /code
+
+COPY ./requirements.txt /code/requirements.txt
+
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+
+# (1)
+COPY ./main.py /code/
+
+# (2)
+CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
+```
+
+1. 直接将`main.py`文件复制到`/code`目录中(不包含任何`./app`目录)。
+
+2. 运行 Uvicorn 并告诉它从 `main` 导入 `app` 对象(而不是从 `app.main` 导入)。
+
+然后调整Uvicorn命令使用新模块`main`而不是`app.main`来导入FastAPI 实例`app`。
+
+## 部署概念
+
+我们再谈谈容器方面的一些相同的[部署概念](concepts.md){.internal-link target=_blank}。
+
+容器主要是一种简化**构建和部署**应用程序的过程的工具,但它们并不强制执行特定的方法来处理这些**部署概念**,并且有几种可能的策略。
+
+**好消息**是,对于每种不同的策略,都有一种方法可以涵盖所有部署概念。 🎉
+
+让我们从容器的角度回顾一下这些**部署概念**:
+
+* HTTPS
+* 启动时运行
+* 重新启动
+* 复制(运行的进程数)
+* 内存
+* 开始前的先前步骤
+
+
+## HTTPS
+
+如果我们只关注 FastAPI 应用程序的 **容器镜像**(以及稍后运行的 **容器**),HTTPS 通常会由另一个工具在 **外部** 处理。
+
+它可以是另一个容器,例如使用
Traefik,处理 **HTTPS** 和 **自动**获取**证书**。
+
+/// tip
+
+Traefik可以与 Docker、Kubernetes 等集成,因此使用它为容器设置和配置 HTTPS 非常容易。
+
+///
+
+或者,HTTPS 可以由云服务商作为其服务之一进行处理(同时仍在容器中运行应用程序)。
+
+## 在启动和重新启动时运行
+
+通常还有另一个工具负责**启动和运行**你的容器。
+
+它可以直接是**Docker**, 或者**Docker Compose**、**Kubernetes**、**云服务**等。
+
+在大多数(或所有)情况下,有一个简单的选项可以在启动时运行容器并在失败时重新启动。 例如,在 Docker 中,它是命令行选项 `--restart`。
+
+如果不使用容器,让应用程序在启动时运行并重新启动可能会很麻烦且困难。 但在大多数情况下,当**使用容器**时,默认情况下会包含该功能。 ✨
+
+## 复制 - 进程数
+
+如果你有一个
集群, 比如 **Kubernetes**、Docker Swarm、Nomad 或其他类似的复杂系统来管理多台机器上的分布式容器,那么你可能希望在**集群级别**处理复制**,而不是在每个容器中使用**进程管理器**(如带有Worker的 Gunicorn) 。
+
+像 Kubernetes 这样的分布式容器管理系统通常有一些集成的方法来处理**容器的复制**,同时仍然支持传入请求的**负载均衡**。 全部都在**集群级别**。
+
+在这些情况下,你可能希望从头开始构建一个 **Docker 镜像**,如[上面所解释](#dockerfile)的那样,安装依赖项并运行 **单个 Uvicorn 进程**,而不是运行 Gunicorn 和 Uvicorn workers这种。
+
+
+### 负载均衡器
+
+使用容器时,通常会有一些组件**监听主端口**。 它可能是处理 **HTTPS** 的 **TLS 终止代理** 或一些类似的工具的另一个容器。
+
+由于该组件将接受请求的**负载**并(希望)以**平衡**的方式在worker之间分配该请求,因此它通常也称为**负载均衡器**。
+
+/// tip
+
+用于 HTTPS **TLS 终止代理** 的相同组件也可能是 **负载均衡器**。
+
+///
+
+当使用容器时,你用来启动和管理容器的同一系统已经具有内部工具来传输来自该**负载均衡器**(也可以是**TLS 终止代理**) 的**网络通信**(例如HTTP请求)到你的应用程序容器。
+
+### 一个负载均衡器 - 多个worker容器
+
+当使用 **Kubernetes** 或类似的分布式容器管理系统时,使用其内部网络机制将允许单个在主 **端口** 上侦听的 **负载均衡器** 将通信(请求)传输到可能的 **多个** 运行你应用程序的容器。
+
+运行你的应用程序的每个容器通常**只有一个进程**(例如,运行 FastAPI 应用程序的 Uvicorn 进程)。 它们都是**相同的容器**,运行相同的东西,但每个容器都有自己的进程、内存等。这样你就可以在 CPU 的**不同核心**, 甚至在**不同的机器**充分利用**并行化(parallelization)**。
+
+具有**负载均衡器**的分布式容器系统将**将请求轮流分配**给你的应用程序的每个容器。 因此,每个请求都可以由运行你的应用程序的多个**复制容器**之一来处理。
+
+通常,这个**负载均衡器**能够处理发送到集群中的*其他*应用程序的请求(例如发送到不同的域,或在不同的 URL 路径前缀下),并正确地将该通信传输到在集群中运行的*其他*应用程序的对应容器。
+
+
+
+
+
+
+### 每个容器一个进程
+
+在这种类型的场景中,你可能希望**每个容器有一个(Uvicorn)进程**,因为你已经在集群级别处理复制。
+
+因此,在这种情况下,你**不会**希望拥有像 Gunicorn 和 Uvicorn worker一样的进程管理器,或者 Uvicorn 使用自己的 Uvicorn worker。 你可能希望每个容器(但可能有多个容器)只有一个**单独的 Uvicorn 进程**。
+
+在容器内拥有另一个进程管理器(就像使用 Gunicorn 或 Uvicorn 管理 Uvicorn 工作线程一样)只会增加**不必要的复杂性**,而你很可能已经在集群系统中处理这些复杂性了。
+
+### 具有多个进程的容器
+
+当然,在某些**特殊情况**,你可能希望拥有 **一个容器**,其中包含 **Gunicorn 进程管理器**,并在其中启动多个 **Uvicorn worker进程**。
+
+在这些情况下,你可以使用 **官方 Docker 镜像**,其中包含 **Gunicorn** 作为运行多个 **Uvicorn 工作进程** 的进程管理器,以及一些默认设置来根据当前情况调整工作进程数量 自动CPU核心。 我将在下面的 [Gunicorn - Uvicorn 官方 Docker 镜像](#official-docker-image-with-gunicorn-uvicorn) 中告诉你更多相关信息。
+
+下面一些什么时候这种做法有意义的示例:
+
+
+#### 一个简单的应用程序
+
+如果你的应用程序**足够简单**,你不需要(至少现在不需要)过多地微调进程数量,并且你可以使用自动默认值,那么你可能需要容器中的进程管理器 (使用官方 Docker 镜像),并且你在**单个服务器**而不是集群上运行它。
+
+#### Docker Compose
+
+你可以使用 **Docker Compose** 部署到**单个服务器**(而不是集群),因此你没有一种简单的方法来管理容器的复制(使用 Docker Compose),同时保留共享网络和 **负载均衡**。
+
+然后,你可能希望拥有一个**单个容器**,其中有一个**进程管理器**,在其中启动**多个worker进程**。
+
+#### Prometheus和其他原因
+
+你还可能有**其他原因**,这将使你更容易拥有一个带有**多个进程**的**单个容器**,而不是拥有每个容器中都有**单个进程**的**多个容器**。
+
+例如(取决于你的设置)你可以在同一个容器中拥有一些工具,例如 Prometheus exporter,该工具应该有权访问**每个请求**。
+
+在这种情况下,如果你有**多个容器**,默认情况下,当 Prometheus 来**读取metrics**时,它每次都会获取**单个容器**的metrics(对于处理该特定请求的容器),而不是获取所有复制容器的**累积metrics**。
+
+在这种情况, 这种做法会更加简单:让**一个容器**具有**多个进程**,并在同一个容器上使用本地工具(例如 Prometheus exporter)收集所有内部进程的 Prometheus 指标并公开单个容器上的这些指标。
+
+---
+
+要点是,这些都**不是**你必须盲目遵循的**一成不变的规则**。 你可以根据这些思路**评估你自己的场景**并决定什么方法是最适合你的的系统,考虑如何管理以下概念:
+
+* 安全性 - HTTPS
+* 启动时运行
+* 重新启动
+* 复制(运行的进程数)
+* 内存
+* 开始前的先前步骤
+
+## 内存
+
+如果你**每个容器运行一个进程**,那么每个容器所消耗的内存或多或少是定义明确的、稳定的且有限的(如果它们是复制的,则不止一个)。
+
+然后,你可以在容器管理系统的配置中设置相同的内存限制和要求(例如在 **Kubernetes** 中)。 这样,它将能够在**可用机器**中**复制容器**,同时考虑容器所需的内存量以及集群中机器中的可用内存量。
+
+如果你的应用程序很**简单**,这可能**不是问题**,并且你可能不需要指定内存限制。 但是,如果你**使用大量内存**(例如使用**机器学习**模型),则应该检查你消耗了多少内存并调整**每台机器**中运行的**容器数量**(也许可以向集群添加更多机器)。
+
+如果你**每个容器运行多个进程**(例如使用官方 Docker 镜像),你必须确保启动的进程数量不会消耗比可用内存**更多的内存**。
+
+## 启动之前的步骤和容器
+
+如果你使用容器(例如 Docker、Kubernetes),那么你可以使用两种主要方法。
+
+
+### 多个容器
+
+如果你有 **多个容器**,可能每个容器都运行一个 **单个进程**(例如,在 **Kubernetes** 集群中),那么你可能希望有一个 **单独的容器** 执行以下操作: 在单个容器中运行单个进程执行**先前步骤**,即运行复制的worker容器之前。
+
+/// info
+
+如果你使用 Kubernetes,这可能是
Init Container。
+
+///
+
+如果在你的用例中,运行前面的步骤**并行多次**没有问题(例如,如果你没有运行数据库迁移,而只是检查数据库是否已准备好),那么你也可以将它们放在开始主进程之前在每个容器中。
+
+### 单容器
+
+如果你有一个简单的设置,使用一个**单个容器**,然后启动多个**工作进程**(或者也只是一个进程),那么你可以在启动进程之前在应用程序同一个容器中运行先前的步骤。 官方 Docker 镜像内部支持这一点。
+
+## 带有 Gunicorn 的官方 Docker 镜像 - Uvicorn
+
+有一个官方 Docker 镜像,其中包含与 Uvicorn worker一起运行的 Gunicorn,如上一章所述:[服务器工作线程 - Gunicorn 与 Uvicorn](server-workers.md){.internal-link target=_blank}。
+
+该镜像主要在上述情况下有用:[具有多个进程和特殊情况的容器](#containers-with-multiple-processes-and-special-cases)。
+
+
+
+*
tiangolo/uvicorn-gunicorn-fastapi.
+
+
+/// warning
+
+你很有可能不需要此基础镜像或任何其他类似的镜像,最好从头开始构建镜像,如[上面所述:为 FastAPI 构建 Docker 镜像](#build-a-docker-image-for-fastapi)。
+
+///
+
+该镜像包含一个**自动调整**机制,用于根据可用的 CPU 核心设置**worker进程数**。
+
+它具有**合理的默认值**,但你仍然可以使用**环境变量**或配置文件更改和更新所有配置。
+
+它还支持通过一个脚本运行
**开始前的先前步骤** 。
+
+/// tip
+
+要查看所有配置和选项,请转到 Docker 镜像页面:
tiangolo/uvicorn-gunicorn-fastapi。
+
+///
+
+### 官方 Docker 镜像上的进程数
+
+此镜像上的**进程数**是根据可用的 CPU **核心**自动计算的。
+
+这意味着它将尝试尽可能多地**榨取**CPU 的**性能**。
+
+你还可以使用 **环境变量** 等配置来调整它。
+
+但这也意味着,由于进程数量取决于容器运行的 CPU,因此**消耗的内存量**也将取决于该数量。
+
+因此,如果你的应用程序消耗大量内存(例如机器学习模型),并且你的服务器有很多 CPU 核心**但内存很少**,那么你的容器最终可能会尝试使用比实际情况更多的内存 可用,并且性能会下降很多(甚至崩溃)。 🚨
+
+### 创建一个`Dockerfile`
+
+以下是如何根据此镜像创建`Dockerfile`:
+
+
+```Dockerfile
+FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
+
+COPY ./requirements.txt /app/requirements.txt
+
+RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
+
+COPY ./app /app
+```
+
+### 更大的应用程序
+
+如果你按照有关创建[具有多个文件的更大应用程序](../tutorial/bigger-applications.md){.internal-link target=_blank}的部分进行操作,你的`Dockerfile`可能看起来这样:
+
+```Dockerfile hl_lines="7"
+FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
+
+COPY ./requirements.txt /app/requirements.txt
+
+RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
+
+COPY ./app /app/app
+```
+
+### 何时使用
+
+如果你使用 **Kubernetes** (或其他)并且你已经在集群级别设置 **复制**,并且具有多个 **容器**。 在这些情况下,你最好按照上面的描述 **从头开始构建镜像**:[为 FastAPI 构建 Docker 镜像](#build-a-docker-image-for-fastapi)。
+
+该镜像主要在[具有多个进程的容器和特殊情况](#containers-with-multiple-processes-and-special-cases)中描述的特殊情况下有用。 例如,如果你的应用程序**足够简单**,基于 CPU 设置默认进程数效果很好,你不想在集群级别手动配置复制,并且不会运行更多进程, 或者你使用 **Docker Compose** 进行部署,在单个服务器上运行等。
+
+## 部署容器镜像
+
+拥有容器(Docker)镜像后,有多种方法可以部署它。
+
+例如:
+
+* 在单个服务器中使用 **Docker Compose**
+* 使用 **Kubernetes** 集群
+* 使用 Docker Swarm 模式集群
+* 使用Nomad等其他工具
+* 使用云服务获取容器镜像并部署它
+
+## Docker 镜像与Poetry
+
+如果你使用
Poetry 来管理项目的依赖项,你可以使用 Docker 多阶段构建:
+
+
+
+```{ .dockerfile .annotate }
+# (1)
+FROM python:3.9 as requirements-stage
+
+# (2)
+WORKDIR /tmp
+
+# (3)
+RUN pip install poetry
+
+# (4)
+COPY ./pyproject.toml ./poetry.lock* /tmp/
+
+# (5)
+RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
+
+# (6)
+FROM python:3.9
+
+# (7)
+WORKDIR /code
+
+# (8)
+COPY --from=requirements-stage /tmp/requirements.txt /code/requirements.txt
+
+# (9)
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+
+# (10)
+COPY ./app /code/app
+
+# (11)
+CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
+```
+
+1. 这是第一阶段,称为`requirements-stage`。
+
+2. 将 `/tmp` 设置为当前工作目录。
+
+ 这是我们生成文件`requirements.txt`的地方
+
+3. 在此阶段安装Poetry。
+
+4. 将`pyproject.toml`和`poetry.lock`文件复制到`/tmp`目录。
+
+ 因为它使用 `./poetry.lock*` (以 `*` 结尾),所以如果该文件尚不可用,它不会崩溃。
+
+5. 生成`requirements.txt`文件。
+
+6. 这是最后阶段,这里的任何内容都将保留在最终的容器镜像中。
+
+7. 将当前工作目录设置为`/code`。
+
+8. 将 `requirements.txt` 文件复制到 `/code` 目录。
+
+ 该文件仅存在于前一个阶段,这就是为什么我们使用 `--from-requirements-stage` 来复制它。
+
+9. 安装生成的`requirements.txt`文件中的依赖项。
+
+10. 将`app`目录复制到`/code`目录。
+
+11. 运行`uvicorn`命令,告诉它使用从`app.main`导入的`app`对象。
+
+/// tip
+
+单击气泡数字可查看每行的作用。
+
+///
+
+**Docker stage** 是 `Dockerfile` 的一部分,用作 **临时容器镜像**,仅用于生成一些稍后使用的文件。
+
+第一阶段仅用于 **安装 Poetry** 并使用 Poetry 的 `pyproject.toml` 文件中的项目依赖项 **生成 `requirements.txt`**。
+
+此`requirements.txt`文件将在**下一阶段**与`pip`一起使用。
+
+在最终的容器镜像中**仅保留最后阶段**。 之前的阶段将被丢弃。
+
+使用 Poetry 时,使用 **Docker 多阶段构建** 是有意义的,因为你实际上并不需要在最终的容器镜像中安装 Poetry 及其依赖项,你 **只需要** 生成用于安装项目依赖项的`requirements.txt`文件。
+
+然后,在下一个(也是最后一个)阶段,你将或多或少地以与前面描述的相同的方式构建镜像。
+
+### 在TLS 终止代理后面 - Poetry
+
+同样,如果你在 Nginx 或 Traefik 等 TLS 终止代理(负载均衡器)后面运行容器,请将选项`--proxy-headers`添加到命令中:
+
+
+```Dockerfile
+CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
+```
+
+## 回顾
+
+使用容器系统(例如使用**Docker**和**Kubernetes**),处理所有**部署概念**变得相当简单:
+
+* HTTPS
+* 启动时运行
+* 重新启动
+* 复制(运行的进程数)
+* 内存
+* 开始前的先前步骤
+
+在大多数情况下,你可能不想使用任何基础镜像,而是基于官方 Python Docker 镜像 **从头开始构建容器镜像** 。
+
+处理好`Dockerfile`和 **Docker 缓存**中指令的**顺序**,你可以**最小化构建时间**,从而最大限度地提高生产力(并避免无聊)。 😎
+
+在某些特殊情况下,你可能需要使用 FastAPI 的官方 Docker 镜像。 🤓
diff --git a/docs/zh/docs/deployment/https.md b/docs/zh/docs/deployment/https.md
new file mode 100644
index 000000000..d994c4add
--- /dev/null
+++ b/docs/zh/docs/deployment/https.md
@@ -0,0 +1,201 @@
+# 关于 HTTPS
+
+人们很容易认为 HTTPS 仅仅是“启用”或“未启用”的东西。
+
+但实际情况比这复杂得多。
+
+/// note | 提示
+
+如果你很赶时间或不在乎,请继续阅读下一部分,下一部分会提供一个step-by-step的教程,告诉你怎么使用不同技术来把一切都配置好。
+
+///
+
+要从用户的视角**了解 HTTPS 的基础知识**,请查看
https://howhttps.works/。
+
+现在,从**开发人员的视角**,在了解 HTTPS 时需要记住以下几点:
+
+* 要使用 HTTPS,**服务器**需要拥有由**第三方**生成的**"证书(certificate)"**。
+ * 这些证书实际上是从第三方**获取**的,而不是“生成”的。
+* 证书有**生命周期**。
+ * 它们会**过期**。
+ * 然后它们需要**更新**,**再次从第三方获取**。
+* 连接的加密发生在 **TCP 层**。
+ * 这是 HTTP 协议**下面的一层**。
+ * 因此,**证书和加密**处理是在 **HTTP之前**完成的。
+* **TCP 不知道域名**。 仅仅知道 IP 地址。
+ * 有关所请求的 **特定域名** 的信息位于 **HTTP 数据**中。
+* **HTTPS 证书**“证明”**某个域名**,但协议和加密发生在 TCP 层,在知道正在处理哪个域名**之前**。
+* **默认情况下**,这意味着你**每个 IP 地址只能拥有一个 HTTPS 证书**。
+ * 无论你的服务器有多大,或者服务器上的每个应用程序有多小。
+ * 不过,对此有一个**解决方案**。
+* **TLS** 协议(在 HTTP 之下的TCP 层处理加密的协议)有一个**扩展**,称为 **
SNI**。
+ * SNI 扩展允许一台服务器(具有 **单个 IP 地址**)拥有 **多个 HTTPS 证书** 并提供 **多个 HTTPS 域名/应用程序**。
+ * 为此,服务器上会有**单独**的一个组件(程序)侦听**公共 IP 地址**,这个组件必须拥有服务器中的**所有 HTTPS 证书**。
+* **获得安全连接后**,通信协议**仍然是HTTP**。
+ * 内容是 **加密过的**,即使它们是通过 **HTTP 协议** 发送的。
+
+通常的做法是在服务器上运行**一个程序/HTTP 服务器**并**管理所有 HTTPS 部分**:接收**加密的 HTTPS 请求**, 将 **解密的 HTTP 请求** 发送到在同一服务器中运行的实际 HTTP 应用程序(在本例中为 **FastAPI** 应用程序),从应用程序中获取 **HTTP 响应**, 使用适当的 **HTTPS 证书**对其进行加密并使用 **HTTPS** 将其发送回客户端。 此服务器通常被称为 **
TLS 终止代理(TLS Termination Proxy)**。
+
+你可以用作 TLS 终止代理的一些选项包括:
+
+* Traefik(也可以处理证书更新)
+* Caddy(也可以处理证书更新)
+* Nginx
+* HAProxy
+
+## Let's Encrypt
+
+在 Let's Encrypt 之前,这些 **HTTPS 证书** 由受信任的第三方出售。
+
+过去,获得这些证书的过程非常繁琐,需要大量的文书工作,而且证书非常昂贵。
+
+但随后 **
Let's Encrypt** 创建了。
+
+它是 Linux 基金会的一个项目。 它以自动方式免费提供 **HTTPS 证书**。 这些证书可以使用所有符合标准的安全加密,并且有效期很短(大约 3 个月),因此**安全性实际上更好**,因为它们的生命周期缩短了。
+
+域可以被安全地验证并自动生成证书。 这还允许自动更新这些证书。
+
+我们的想法是自动获取和更新这些证书,以便你可以永远免费拥有**安全的 HTTPS**。
+
+## 面向开发人员的 HTTPS
+
+这里有一个 HTTPS API 看起来是什么样的示例,我们会分步说明,并且主要关注对开发人员重要的部分。
+
+
+### 域名
+
+第一步我们要先**获取**一些**域名(Domain Name)**。 然后可以在 DNS 服务器(可能是你的同一家云服务商提供的)中配置它。
+
+你可能拥有一个云服务器(虚拟机)或类似的东西,并且它会有一个
固定 **公共IP地址**。
+
+在 DNS 服务器中,你可以配置一条记录(“A 记录”)以将 **你的域名** 指向你服务器的公共 **IP 地址**。
+
+这个操作一般只需要在最开始执行一次。
+
+/// tip
+
+域名这部分发生在 HTTPS 之前,由于这一切都依赖于域名和 IP 地址,所以先在这里提一下。
+
+///
+
+### DNS
+
+现在让我们关注真正的 HTTPS 部分。
+
+首先,浏览器将通过 **DNS 服务器** 查询**域名的IP** 是什么,在本例中为 `someapp.example.com`。
+
+DNS 服务器会告诉浏览器使用某个特定的 **IP 地址**。 这将是你在 DNS 服务器中为你的服务器配置的公共 IP 地址。
+
+

+
+### TLS 握手开始
+
+然后,浏览器将在**端口 443**(HTTPS 端口)上与该 IP 地址进行通信。
+
+通信的第一部分只是建立客户端和服务器之间的连接并决定它们将使用的加密密钥等。
+
+

+
+客户端和服务器之间建立 TLS 连接的过程称为 **TLS 握手**。
+
+### 带有 SNI 扩展的 TLS
+
+**服务器中只有一个进程**可以侦听特定 **IP 地址**的特定 **端口**。 可能有其他进程在同一 IP 地址的其他端口上侦听,但每个 IP 地址和端口组合只有一个进程。
+
+TLS (HTTPS) 默认使用端口`443`。 这就是我们需要的端口。
+
+由于只有一个进程可以监听此端口,因此监听端口的进程将是 **TLS 终止代理**。
+
+TLS 终止代理可以访问一个或多个 **TLS 证书**(HTTPS 证书)。
+
+使用上面讨论的 **SNI 扩展**,TLS 终止代理将检查应该用于此连接的可用 TLS (HTTPS) 证书,并使用与客户端期望的域名相匹配的证书。
+
+在这种情况下,它将使用`someapp.example.com`的证书。
+
+

+
+客户端已经**信任**生成该 TLS 证书的实体(在本例中为 Let's Encrypt,但我们稍后会看到),因此它可以**验证**该证书是否有效。
+
+然后,通过使用证书,客户端和 TLS 终止代理 **决定如何加密** **TCP 通信** 的其余部分。 这就完成了 **TLS 握手** 部分。
+
+此后,客户端和服务器就拥有了**加密的 TCP 连接**,这就是 TLS 提供的功能。 然后他们可以使用该连接来启动实际的 **HTTP 通信**。
+
+这就是 **HTTPS**,它只是 **安全 TLS 连接** 内的普通 **HTTP**,而不是纯粹的(未加密的)TCP 连接。
+
+/// tip
+
+请注意,通信加密发生在 **TCP 层**,而不是 HTTP 层。
+
+///
+
+### HTTPS 请求
+
+现在客户端和服务器(特别是浏览器和 TLS 终止代理)具有 **加密的 TCP 连接**,它们可以开始 **HTTP 通信**。
+
+接下来,客户端发送一个 **HTTPS 请求**。 这其实只是一个通过 TLS 加密连接的 HTTP 请求。
+
+

+
+### 解密请求
+
+TLS 终止代理将使用协商好的加密算法**解密请求**,并将**(解密的)HTTP 请求**传输到运行应用程序的进程(例如运行 FastAPI 应用的 Uvicorn 进程)。
+
+

+
+### HTTP 响应
+
+应用程序将处理请求并向 TLS 终止代理发送**(未加密)HTTP 响应**。
+
+

+
+### HTTPS 响应
+
+然后,TLS 终止代理将使用之前协商的加密算法(以`someapp.example.com`的证书开头)对响应进行加密,并将其发送回浏览器。
+
+接下来,浏览器将验证响应是否有效和是否使用了正确的加密密钥等。然后它会**解密响应**并处理它。
+
+

+
+客户端(浏览器)将知道响应来自正确的服务器,因为它使用了他们之前使用 **HTTPS 证书** 协商出的加密算法。
+
+### 多个应用程序
+
+在同一台(或多台)服务器中,可能存在**多个应用程序**,例如其他 API 程序或数据库。
+
+只有一个进程可以处理特定的 IP 和端口(在我们的示例中为 TLS 终止代理),但其他应用程序/进程也可以在服务器上运行,只要它们不尝试使用相同的 **公共 IP 和端口的组合**。
+
+

+
+这样,TLS 终止代理就可以为多个应用程序处理**多个域名**的 HTTPS 和证书,然后在每种情况下将请求传输到正确的应用程序。
+
+### 证书更新
+
+在未来的某个时候,每个证书都会**过期**(大约在获得证书后 3 个月)。
+
+然后,会有另一个程序(在某些情况下是另一个程序,在某些情况下可能是同一个 TLS 终止代理)与 Let's Encrypt 通信并更新证书。
+
+

+
+**TLS 证书** **与域名相关联**,而不是与 IP 地址相关联。
+
+因此,要更新证书,更新程序需要向权威机构(Let's Encrypt)**证明**它确实**“拥有”并控制该域名**。
+
+有多种方法可以做到这一点。 一些流行的方式是:
+
+* **修改一些DNS记录**。
+ * 为此,续订程序需要支持 DNS 提供商的 API,因此,要看你使用的 DNS 提供商是否提供这一功能。
+* **在与域名关联的公共 IP 地址上作为服务器运行**(至少在证书获取过程中)。
+ * 正如我们上面所说,只有一个进程可以监听特定的 IP 和端口。
+ * 这就是当同一个 TLS 终止代理还负责证书续订过程时它非常有用的原因之一。
+ * 否则,你可能需要暂时停止 TLS 终止代理,启动续订程序以获取证书,然后使用 TLS 终止代理配置它们,然后重新启动 TLS 终止代理。 这并不理想,因为你的应用程序在 TLS 终止代理关闭期间将不可用。
+
+通过拥有一个**单独的系统来使用 TLS 终止代理来处理 HTTPS**, 而不是直接将 TLS 证书与应用程序服务器一起使用 (例如 Uvicorn),你可以在
+更新证书的过程中同时保持提供服务。
+
+## 回顾
+
+拥有**HTTPS** 非常重要,并且在大多数情况下相当**关键**。 作为开发人员,你围绕 HTTPS 所做的大部分努力就是**理解这些概念**以及它们的工作原理。
+
+一旦你了解了**面向开发人员的 HTTPS** 的基础知识,你就可以轻松组合和配置不同的工具,以帮助你以简单的方式管理一切。
+
+在接下来的一些章节中,我将向你展示几个为 **FastAPI** 应用程序设置 **HTTPS** 的具体示例。 🔒
diff --git a/docs/zh/docs/deployment/index.md b/docs/zh/docs/deployment/index.md
new file mode 100644
index 000000000..1ec0c5c5b
--- /dev/null
+++ b/docs/zh/docs/deployment/index.md
@@ -0,0 +1,21 @@
+# 部署
+
+部署 **FastAPI** 应用程序相对容易。
+
+## 部署是什么意思
+
+**部署**应用程序意味着执行必要的步骤以使其**可供用户使用**。
+
+对于**Web API**来说,通常涉及将上传到**云服务器**中,搭配一个性能和稳定性都不错的**服务器程序**,以便你的**用户**可以高效地**访问**你的应用程序,而不会出现中断或其他问题。
+
+这与**开发**阶段形成鲜明对比,在**开发**阶段,你不断更改代码、破坏代码、修复代码, 来回停止和重启服务器等。
+
+## 部署策略
+
+根据你的使用场景和使用的工具,有多种方法可以实现此目的。
+
+你可以使用一些工具自行**部署服务器**,你也可以使用能为你完成部分工作的**云服务**,或其他可能的选项。
+
+我将向你展示在部署 **FastAPI** 应用程序时你可能应该记住的一些主要概念(尽管其中大部分适用于任何其他类型的 Web 应用程序)。
+
+在接下来的部分中,你将看到更多需要记住的细节以及一些技巧。 ✨
diff --git a/docs/zh/docs/deployment/manually.md b/docs/zh/docs/deployment/manually.md
new file mode 100644
index 000000000..3dc5942e3
--- /dev/null
+++ b/docs/zh/docs/deployment/manually.md
@@ -0,0 +1,158 @@
+# 手动运行服务器
+
+## 使用 `fastapi run` 命令
+
+简而言之,使用 `fastapi run` 来运行您的 FastAPI 应用程序:
+
+
+
+```console
+$ fastapi run main.py
+
+ FastAPI Starting production server 🚀
+
+ Searching for package file structure from directories
+ with __init__.py files
+ Importing from /home/user/code/awesomeapp
+
+ module 🐍 main.py
+
+ code Importing the FastAPI app object from the module with
+ the following code:
+
+ from main import app
+
+ app Using import string: main:app
+
+ server Server started at http://0.0.0.0:8000
+ server Documentation at http://0.0.0.0:8000/docs
+
+ Logs:
+
+ INFO Started server process [2306215]
+ INFO Waiting for application startup.
+ INFO Application startup complete.
+ INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C
+ to quit)
+```
+
+
+
+这在大多数情况下都能正常运行。😎
+
+例如,您可以使用该命令在容器、服务器等环境中启动您的 **FastAPI** 应用。
+
+## ASGI 服务器
+
+让我们深入了解一些细节。
+
+FastAPI 使用了一种用于构建 Python Web 框架和服务器的标准,称为
ASGI。FastAPI 本质上是一个 ASGI Web 框架。
+
+要在远程服务器上运行 **FastAPI** 应用(或任何其他 ASGI 应用),您需要一个 ASGI 服务器程序,例如 **Uvicorn**。它是 `fastapi` 命令默认使用的 ASGI 服务器。
+
+除此之外,还有其他一些可选的 ASGI 服务器,例如:
+
+*
Uvicorn:高性能 ASGI 服务器。
+*
Hypercorn:与 HTTP/2 和 Trio 等兼容的 ASGI 服务器。
+*
Daphne:为 Django Channels 构建的 ASGI 服务器。
+*
Granian:基于 Rust 的 HTTP 服务器,专为 Python 应用设计。
+*
NGINX Unit:NGINX Unit 是一个轻量级且灵活的 Web 应用运行时环境。
+
+## 服务器主机和服务器程序
+
+关于名称,有一个小细节需要记住。 💡
+
+“**服务器**”一词通常用于指远程/云计算机(物理机或虚拟机)以及在该计算机上运行的程序(例如 Uvicorn)。
+
+请记住,当您一般读到“服务器”这个名词时,它可能指的是这两者之一。
+
+当提到远程主机时,通常将其称为**服务器**,但也称为**机器**(machine)、**VM**(虚拟机)、**节点**。 这些都是指某种类型的远程计算机,通常运行 Linux,您可以在其中运行程序。
+
+
+## 安装服务器程序
+
+当您安装 FastAPI 时,它自带一个生产环境服务器——Uvicorn,并且您可以使用 `fastapi run` 命令来启动它。
+
+不过,您也可以手动安装 ASGI 服务器。
+
+请确保您创建并激活一个[虚拟环境](../virtual-environments.md){.internal-link target=_blank},然后再安装服务器应用程序。
+
+例如,要安装 Uvicorn,可以运行以下命令:
+
+
+
+```console
+$ pip install "uvicorn[standard]"
+
+---> 100%
+```
+
+
+
+类似的流程也适用于任何其他 ASGI 服务器程序。
+
+/// tip
+
+通过添加 `standard` 选项,Uvicorn 将安装并使用一些推荐的额外依赖项。
+
+其中包括 `uvloop`,这是 `asyncio` 的高性能替代方案,能够显著提升并发性能。
+
+当您使用 `pip install "fastapi[standard]"` 安装 FastAPI 时,实际上也会安装 `uvicorn[standard]`。
+
+///
+
+## 运行服务器程序
+
+如果您手动安装了 ASGI 服务器,通常需要以特定格式传递一个导入字符串,以便服务器能够正确导入您的 FastAPI 应用:
+
+
+
+```console
+$ uvicorn main:app --host 0.0.0.0 --port 80
+
+INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
+```
+
+
+
+/// note
+
+命令 `uvicorn main:app` 的含义如下:
+
+* `main`:指的是 `main.py` 文件(即 Python “模块”)。
+* `app`:指的是 `main.py` 文件中通过 `app = FastAPI()` 创建的对象。
+
+它等价于以下导入语句:
+
+```Python
+from main import app
+```
+
+///
+
+每种 ASGI 服务器程序通常都会有类似的命令,您可以在它们的官方文档中找到更多信息。
+
+/// warning
+
+Uvicorn 和其他服务器支持 `--reload` 选项,该选项在开发过程中非常有用。
+
+但 `--reload` 选项会消耗更多资源,且相对不稳定。
+
+它对于**开发阶段**非常有帮助,但在**生产环境**中**不应该**使用。
+
+///
+
+## 部署概念
+
+这些示例运行服务器程序(例如 Uvicorn),启动**单个进程**,在所有 IP(`0.0.0.0`)上监听预定义端口(例如`80`)。
+
+这是基本思路。 但您可能需要处理一些其他事情,例如:
+
+* 安全性 - HTTPS
+* 启动时运行
+* 重新启动
+* 复制(运行的进程数)
+* 内存
+* 开始前的步骤
+
+在接下来的章节中,我将向您详细介绍每个概念、如何思考它们,以及一些具体示例以及处理它们的策略。 🚀
diff --git a/docs/zh/docs/deployment/server-workers.md b/docs/zh/docs/deployment/server-workers.md
new file mode 100644
index 000000000..e46ba7a09
--- /dev/null
+++ b/docs/zh/docs/deployment/server-workers.md
@@ -0,0 +1,139 @@
+# 服务器工作进程(Workers) - 使用 Uvicorn 的多工作进程模式
+
+让我们回顾一下之前的部署概念:
+
+* 安全性 - HTTPS
+* 启动时运行
+* 重新启动
+* **复制(运行的进程数)**
+* 内存
+* 启动前的先前步骤
+
+到目前为止,在文档中的所有教程中,您可能一直是在运行一个**服务器程序**,例如使用 `fastapi` 命令来启动 Uvicorn,而它默认运行的是**单进程模式**。
+
+部署应用程序时,您可能希望进行一些**进程复制**,以利用**多核** CPU 并能够处理更多请求。
+
+正如您在上一章有关[部署概念](concepts.md){.internal-link target=_blank}中看到的,您可以使用多种策略。
+
+在本章节中,我将向您展示如何使用 `fastapi` 命令或直接使用 `uvicorn` 命令以**多工作进程模式**运行 **Uvicorn**。
+
+/// info
+
+如果您正在使用容器,例如 Docker 或 Kubernetes,我将在下一章中告诉您更多相关信息:[容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank}。
+
+比较特别的是,在 **Kubernetes** 环境中运行时,您通常**不需要**使用多个工作进程,而是**每个容器运行一个 Uvicorn 进程**。不过,我会在本章节的后续部分详细介绍这一点。
+
+///
+
+## 多个工作进程
+
+您可以使用 `--workers` 命令行选项来启动多个工作进程:
+
+//// tab | `fastapi`
+
+如果您使用 `fastapi` 命令:
+
+
+
+```console
+$ fastapi run --workers 4 main.py
+
+ FastAPI Starting production server 🚀
+
+ Searching for package file structure from directories with
+ __init__.py files
+ Importing from /home/user/code/awesomeapp
+
+ module 🐍 main.py
+
+ code Importing the FastAPI app object from the module with the
+ following code:
+
+ from main import app
+
+ app Using import string: main:app
+
+ server Server started at http://0.0.0.0:8000
+ server Documentation at http://0.0.0.0:8000/docs
+
+ Logs:
+
+ INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to
+ quit)
+ INFO Started parent process [27365]
+ INFO Started server process [27368]
+ INFO Started server process [27369]
+ INFO Started server process [27370]
+ INFO Started server process [27367]
+ INFO Waiting for application startup.
+ INFO Waiting for application startup.
+ INFO Waiting for application startup.
+ INFO Waiting for application startup.
+ INFO Application startup complete.
+ INFO Application startup complete.
+ INFO Application startup complete.
+ INFO Application startup complete.
+```
+
+
+
+////
+
+//// tab | `uvicorn`
+
+如果您更想要直接使用 `uvicorn` 命令:
+
+
+
+```console
+$ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
+INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
+INFO: Started parent process [27365]
+INFO: Started server process [27368]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+INFO: Started server process [27369]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+INFO: Started server process [27370]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+INFO: Started server process [27367]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+////
+
+这里唯一的新选项是 `--workers` 告诉 Uvicorn 启动 4 个工作进程。
+
+您还可以看到它显示了每个进程的 **PID**,父进程(这是**进程管理器**)的 PID 为`27365`,每个工作进程的 PID 为:`27368`、`27369`, `27370`和`27367`。
+
+## 部署概念
+
+在这里,您学习了如何使用多个**工作进程(workers)**来让应用程序的执行**并行化**,充分利用 CPU 的**多核性能**,并能够处理**更多的请求**。
+
+从上面的部署概念列表来看,使用worker主要有助于**复制**部分,并对**重新启动**有一点帮助,但您仍然需要照顾其他部分:
+
+* **安全 - HTTPS**
+* **启动时运行**
+* ***重新启动***
+* 复制(运行的进程数)
+* **内存**
+* **启动之前的先前步骤**
+
+## 容器和 Docker
+
+在关于 [容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank} 的下一章中,我将介绍一些可用于处理其他**部署概念**的策略。
+
+我将向您展示如何**从零开始构建自己的镜像**,以运行一个单独的 Uvicorn 进程。这个过程相对简单,并且在使用 **Kubernetes** 等分布式容器管理系统时,这通常是您需要采取的方法。
+
+## 回顾
+
+您可以在使用 `fastapi` 或 `uvicorn` 命令时,通过 `--workers` CLI 选项启用多个工作进程(workers),以充分利用**多核 CPU**,以**并行运行多个进程**。
+
+如果您要设置**自己的部署系统**,同时自己处理其他部署概念,则可以使用这些工具和想法。
+
+请查看下一章,了解带有容器(例如 Docker 和 Kubernetes)的 **FastAPI**。 您将看到这些工具也有简单的方法来解决其他**部署概念**。 ✨
diff --git a/docs/zh/docs/deployment/versions.md b/docs/zh/docs/deployment/versions.md
new file mode 100644
index 000000000..228bb0765
--- /dev/null
+++ b/docs/zh/docs/deployment/versions.md
@@ -0,0 +1,93 @@
+# 关于 FastAPI 版本
+
+**FastAPI** 已在许多应用程序和系统的生产环境中使用。 并且测试覆盖率保持在100%。 但其开发进度仍在快速推进。
+
+经常添加新功能,定期修复错误,并且代码仍在持续改进。
+
+这就是为什么当前版本仍然是`0.x.x`,这反映出每个版本都可能有Breaking changes。 这遵循
语义版本控制的约定。
+
+你现在就可以使用 **FastAPI** 创建生产环境应用程序(你可能已经这样做了一段时间),你只需确保使用的版本可以与其余代码正确配合即可。
+
+## 固定你的 `fastapi` 版本
+
+你应该做的第一件事是将你正在使用的 **FastAPI** 版本“固定”到你知道适用于你的应用程序的特定最新版本。
+
+例如,假设你在应用程序中使用版本`0.45.0`。
+
+如果你使用`requirements.txt`文件,你可以使用以下命令指定版本:
+
+````txt
+fastapi==0.45.0
+````
+
+这意味着你将使用版本`0.45.0`。
+
+或者你也可以将其固定为:
+
+````txt
+fastapi>=0.45.0,<0.46.0
+````
+
+这意味着你将使用`0.45.0`或更高版本,但低于`0.46.0`,例如,版本`0.45.2`仍会被接受。
+
+如果你使用任何其他工具来管理你的安装,例如 Poetry、Pipenv 或其他工具,它们都有一种定义包的特定版本的方法。
+
+## 可用版本
+
+你可以在[发行说明](../release-notes.md){.internal-link target=_blank}中查看可用版本(例如查看当前最新版本)。
+
+## 关于版本
+
+遵循语义版本控制约定,任何低于`1.0.0`的版本都可能会添加 breaking changes。
+
+FastAPI 还遵循这样的约定:任何`PATCH`版本更改都是为了bug修复和non-breaking changes。
+
+/// tip
+
+"PATCH"是最后一个数字,例如,在`0.2.3`中,PATCH版本是`3`。
+
+///
+
+因此,你应该能够固定到如下版本:
+
+```txt
+fastapi>=0.45.0,<0.46.0
+```
+
+"MINOR"版本中会添加breaking changes和新功能。
+
+/// tip
+
+"MINOR"是中间的数字,例如,在`0.2.3`中,MINOR版本是`2`。
+
+///
+
+## 升级FastAPI版本
+
+你应该为你的应用程序添加测试。
+
+使用 **FastAPI** 编写测试非常简单(感谢 Starlette),请参考文档:[测试](../tutorial/testing.md){.internal-link target=_blank}
+
+添加测试后,你可以将 **FastAPI** 版本升级到更新版本,并通过运行测试来确保所有代码都能正常工作。
+
+如果一切正常,或者在进行必要的更改之后,并且所有测试都通过了,那么你可以将`fastapi`固定到新的版本。
+
+## 关于Starlette
+
+你不应该固定`starlette`的版本。
+
+不同版本的 **FastAPI** 将使用特定的较新版本的 Starlette。
+
+因此,**FastAPI** 自己可以使用正确的 Starlette 版本。
+
+## 关于 Pydantic
+
+Pydantic 包含针对 **FastAPI** 的测试及其自己的测试,因此 Pydantic 的新版本(`1.0.0`以上)始终与 FastAPI 兼容。
+
+你可以将 Pydantic 固定到适合你的`1.0.0`以上和`2.0.0`以下的任何版本。
+
+例如:
+
+````txt
+pydantic>=1.2.0,<2.0.0
+````
diff --git a/docs/zh/docs/environment-variables.md b/docs/zh/docs/environment-variables.md
new file mode 100644
index 000000000..812278051
--- /dev/null
+++ b/docs/zh/docs/environment-variables.md
@@ -0,0 +1,298 @@
+# 环境变量
+
+/// tip
+
+如果你已经知道什么是“环境变量”并且知道如何使用它们,你可以放心跳过这一部分。
+
+///
+
+环境变量(也称为“**env var**”)是一个独立于 Python 代码**之外**的变量,它存在于**操作系统**中,可以被你的 Python 代码(或其他程序)读取。
+
+环境变量对于处理应用程序**设置**、作为 Python **安装**的一部分等方面非常有用。
+
+## 创建和使用环境变量
+
+你在 **shell(终端)**中就可以**创建**和使用环境变量,并不需要用到 Python:
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+// 你可以使用以下命令创建一个名为 MY_NAME 的环境变量
+$ export MY_NAME="Wade Wilson"
+
+// 然后,你可以在其他程序中使用它,例如
+$ echo "Hello $MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+// 创建一个名为 MY_NAME 的环境变量
+$ $Env:MY_NAME = "Wade Wilson"
+
+// 在其他程序中使用它,例如
+$ echo "Hello $Env:MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+## 在 Python 中读取环境变量
+
+你也可以在 Python **之外**的终端中创建环境变量(或使用任何其他方法),然后在 Python 中**读取**它们。
+
+例如,你可以创建一个名为 `main.py` 的文件,其中包含以下内容:
+
+```Python hl_lines="3"
+import os
+
+name = os.getenv("MY_NAME", "World")
+print(f"Hello {name} from Python")
+```
+
+/// tip
+
+第二个参数是
`os.getenv()` 的默认返回值。
+
+如果没有提供,默认值为 `None`,这里我们提供 `"World"` 作为默认值。
+
+///
+
+然后你可以调用这个 Python 程序:
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+// 这里我们还没有设置环境变量
+$ python main.py
+
+// 因为我们没有设置环境变量,所以我们得到的是默认值
+
+Hello World from Python
+
+// 但是如果我们事先创建过一个环境变量
+$ export MY_NAME="Wade Wilson"
+
+// 然后再次调用程序
+$ python main.py
+
+// 现在就可以读取到环境变量了
+
+Hello Wade Wilson from Python
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+// 这里我们还没有设置环境变量
+$ python main.py
+
+// 因为我们没有设置环境变量,所以我们得到的是默认值
+
+Hello World from Python
+
+// 但是如果我们事先创建过一个环境变量
+$ $Env:MY_NAME = "Wade Wilson"
+
+// 然后再次调用程序
+$ python main.py
+
+// 现在就可以读取到环境变量了
+
+Hello Wade Wilson from Python
+```
+
+
+
+////
+
+由于环境变量可以在代码之外设置、但可以被代码读取,并且不必与其他文件一起存储(提交到 `git`),因此通常用于配置或**设置**。
+
+你还可以为**特定的程序调用**创建特定的环境变量,该环境变量仅对该程序可用,且仅在其运行期间有效。
+
+要实现这一点,只需在同一行内、程序本身之前创建它:
+
+
+
+```console
+// 在这个程序调用的同一行中创建一个名为 MY_NAME 的环境变量
+$ MY_NAME="Wade Wilson" python main.py
+
+// 现在就可以读取到环境变量了
+
+Hello Wade Wilson from Python
+
+// 在此之后这个环境变量将不会依然存在
+$ python main.py
+
+Hello World from Python
+```
+
+
+
+/// tip
+
+你可以在
The Twelve-Factor App: 配置中了解更多信息。
+
+///
+
+## 类型和验证
+
+这些环境变量只能处理**文本字符串**,因为它们是处于 Python 范畴之外的,必须与其他程序和操作系统的其余部分兼容(甚至与不同的操作系统兼容,如 Linux、Windows、macOS)。
+
+这意味着从环境变量中读取的**任何值**在 Python 中都将是一个 `str`,任何类型转换或验证都必须在代码中完成。
+
+你将在[高级用户指南 - 设置和环境变量](./advanced/settings.md)中了解更多关于使用环境变量处理**应用程序设置**的信息。
+
+## `PATH` 环境变量
+
+有一个**特殊的**环境变量称为 **`PATH`**,操作系统(Linux、macOS、Windows)用它来查找要运行的程序。
+
+`PATH` 变量的值是一个长字符串,由 Linux 和 macOS 上的冒号 `:` 分隔的目录组成,而在 Windows 上则是由分号 `;` 分隔的。
+
+例如,`PATH` 环境变量可能如下所示:
+
+//// tab | Linux, macOS
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
+```
+
+这意味着系统应该在以下目录中查找程序:
+
+- `/usr/local/bin`
+- `/usr/bin`
+- `/bin`
+- `/usr/sbin`
+- `/sbin`
+
+////
+
+//// tab | Windows
+
+```plaintext
+C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32
+```
+
+这意味着系统应该在以下目录中查找程序:
+
+- `C:\Program Files\Python312\Scripts`
+- `C:\Program Files\Python312`
+- `C:\Windows\System32`
+
+////
+
+当你在终端中输入一个**命令**时,操作系统会在 `PATH` 环境变量中列出的**每个目录**中**查找**程序。
+
+例如,当你在终端中输入 `python` 时,操作系统会在该列表中的**第一个目录**中查找名为 `python` 的程序。
+
+如果找到了,那么操作系统将**使用它**;否则,操作系统会继续在**其他目录**中查找。
+
+### 安装 Python 和更新 `PATH`
+
+安装 Python 时,可能会询问你是否要更新 `PATH` 环境变量。
+
+//// tab | Linux, macOS
+
+假设你安装 Python 并最终将其安装在了目录 `/opt/custompython/bin` 中。
+
+如果你同意更新 `PATH` 环境变量,那么安装程序将会将 `/opt/custompython/bin` 添加到 `PATH` 环境变量中。
+
+它看起来大概会像这样:
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin
+```
+
+如此一来,当你在终端中输入 `python` 时,系统会在 `/opt/custompython/bin` 中找到 Python 程序(最后一个目录)并使用它。
+
+////
+
+//// tab | Windows
+
+假设你安装 Python 并最终将其安装在了目录 `C:\opt\custompython\bin` 中。
+
+如果你同意更新 `PATH` 环境变量 (在 Python 安装程序中,这个操作是名为 `Add Python x.xx to PATH` 的复选框 —— 译者注),那么安装程序将会将 `C:\opt\custompython\bin` 添加到 `PATH` 环境变量中。
+
+```plaintext
+C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin
+```
+
+如此一来,当你在终端中输入 `python` 时,系统会在 `C:\opt\custompython\bin` 中找到 Python 程序(最后一个目录)并使用它。
+
+////
+
+因此,如果你输入:
+
+
+
+```console
+$ python
+```
+
+
+
+//// tab | Linux, macOS
+
+系统会在 `/opt/custompython/bin` 中**找到** `python` 程序并运行它。
+
+这和输入以下命令大致等价:
+
+
+
+```console
+$ /opt/custompython/bin/python
+```
+
+
+
+////
+
+//// tab | Windows
+
+系统会在 `C:\opt\custompython\bin\python` 中**找到** `python` 程序并运行它。
+
+这和输入以下命令大致等价:
+
+
+
+```console
+$ C:\opt\custompython\bin\python
+```
+
+
+
+////
+
+当学习[虚拟环境](virtual-environments.md)时,这些信息将会很有用。
+
+## 结论
+
+通过这个教程,你应该对**环境变量**是什么以及如何在 Python 中使用它们有了基本的了解。
+
+你也可以在
环境变量 - 维基百科 (
Wikipedia for Environment Variable) 中了解更多关于它们的信息。
+
+在许多情况下,环境变量的用途和适用性并不是很明显。但是在开发过程中,它们会在许多不同的场景中出现,因此了解它们是很有必要的。
+
+例如,你将在下一节关于[虚拟环境](virtual-environments.md)中需要这些信息。
diff --git a/docs/zh/docs/fastapi-cli.md b/docs/zh/docs/fastapi-cli.md
new file mode 100644
index 000000000..8a70e1d80
--- /dev/null
+++ b/docs/zh/docs/fastapi-cli.md
@@ -0,0 +1,79 @@
+# FastAPI CLI
+
+**FastAPI CLI** 是一个命令行程序,你可以用它来部署和运行你的 FastAPI 应用程序,管理你的 FastAPI 项目,等等。
+
+当你安装 FastAPI 时(例如使用 `pip install FastAPI` 命令),会包含一个名为 `fastapi-cli` 的软件包,该软件包在终端中提供 `fastapi` 命令。
+
+要在开发环境中运行你的 FastAPI 应用,你可以使用 `fastapi dev` 命令:
+
+
+
+```console
+$ fastapi dev main.py
+
+ FastAPI Starting development server 🚀
+
+ Searching for package file structure from directories with
+ __init__.py files
+ Importing from /home/user/code/awesomeapp
+
+ module 🐍 main.py
+
+ code Importing the FastAPI app object from the module with the
+ following code:
+
+ from main import app
+
+ app Using import string: main:app
+
+ server Server started at http://127.0.0.1:8000
+ server Documentation at http://127.0.0.1:8000/docs
+
+ tip Running in development mode, for production use:
+ fastapi run
+
+ Logs:
+
+ INFO Will watch for changes in these directories:
+ ['/home/user/code/awesomeapp']
+ INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to
+ quit)
+ INFO Started reloader process [383138] using WatchFiles
+ INFO Started server process [383153]
+ INFO Waiting for application startup.
+ INFO Application startup complete.
+```
+
+
+
+该命令行程序 `fastapi` 就是 **FastAPI CLI**。
+
+FastAPI CLI 接收你的 Python 程序路径,自动检测包含 FastAPI 的变量(通常命名为 `app`)及其导入方式,然后启动服务。
+
+在生产环境中,你应该使用 `fastapi run` 命令。🚀
+
+在内部,**FastAPI CLI** 使用了
Uvicorn,这是一个高性能、适用于生产环境的 ASGI 服务器。😎
+
+## `fastapi dev`
+
+当你运行 `fastapi dev` 时,它将以开发模式运行。
+
+默认情况下,它会启用**自动重载**,因此当你更改代码时,它会自动重新加载服务器。该功能是资源密集型的,且相较不启用时更不稳定,因此你应该仅在开发环境下使用它。
+
+默认情况下,它将监听 IP 地址 `127.0.0.1`,这是你的机器与自身通信的 IP 地址(`localhost`)。
+
+## `fastapi run`
+
+当你运行 `fastapi run` 时,它默认以生产环境模式运行。
+
+默认情况下,**自动重载是禁用的**。
+
+它将监听 IP 地址 `0.0.0.0`,即所有可用的 IP 地址,这样任何能够与该机器通信的人都可以公开访问它。这通常是你在生产环境中运行它的方式,例如在容器中运行。
+
+在大多数情况下,你会(且应该)有一个“终止代理”在上层为你处理 HTTPS,这取决于你如何部署应用程序,你的服务提供商可能会为你处理此事,或者你可能需要自己设置。
+
+/// tip | 提示
+
+你可以在 [deployment documentation](deployment/index.md){.internal-link target=_blank} 获得更多信息。
+
+///
diff --git a/docs/zh/docs/fastapi-people.md b/docs/zh/docs/fastapi-people.md
deleted file mode 100644
index 75651592d..000000000
--- a/docs/zh/docs/fastapi-people.md
+++ /dev/null
@@ -1,174 +0,0 @@
-# FastAPI 社区
-
-FastAPI 有一个非常棒的社区,它欢迎来自各个领域和背景的朋友。
-
-## 创建者 & 维护者
-
-嘿! 👋
-
-这就是我:
-
-{% if people %}
-
-{% for user in people.maintainers %}
-
-
-{% endfor %}
-
-
-{% endif %}
-
-我是 **FastAPI** 的创建者和维护者. 你能在 [帮助 FastAPI - 获取帮助 - 与作者联系](help-fastapi.md#connect-with-the-author){.internal-link target=_blank} 阅读有关此内容的更多信息。
-
-...但是在这里我想向您展示社区。
-
----
-
-**FastAPI** 得到了社区的大力支持。因此我想突出他们的贡献。
-
-这些人:
-
-* [帮助他人解决 GitHub 的 issues](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}。
-* [创建 Pull Requests](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}。
-* 审核 Pull Requests, 对于 [翻译](contributing.md#translations){.internal-link target=_blank} 尤为重要。
-
-向他们致以掌声。 👏 🙇
-
-## 上个月最活跃的用户
-
-上个月这些用户致力于 [帮助他人解决 GitHub 的 issues](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}。
-
-{% if people %}
-
-{% for user in people.last_month_active %}
-
-
-{% endfor %}
-
-
-{% endif %}
-
-## 专家组
-
-以下是 **FastAPI 专家**。 🤓
-
-这些用户一直以来致力于 [帮助他人解决 GitHub 的 issues](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}。
-
-他们通过帮助许多人而被证明是专家。✨
-
-{% if people %}
-
-{% for user in people.experts %}
-
-
-{% endfor %}
-
-
-{% endif %}
-
-## 杰出贡献者
-
-以下是 **杰出的贡献者**。 👷
-
-这些用户 [创建了最多已被合并的 Pull Requests](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}。
-
-他们贡献了源代码,文档,翻译等。 📦
-
-{% if people %}
-
-{% for user in people.top_contributors %}
-
-
-{% endfor %}
-
-
-{% endif %}
-
-还有很多其他贡献者(超过100个),你可以在
FastAPI GitHub 贡献者页面 中看到他们。👷
-
-## 杰出审核者
-
-以下用户是「杰出的评审者」。 🕵️
-
-### 翻译审核
-
-我只会说少数几种语言(而且还不是很流利 😅)。所以,具备[能力去批准文档翻译](contributing.md#translations){.internal-link target=_blank} 是这些评审者们。如果没有它们,就不会有多语言文档。
-
----
-
-**杰出的评审者** 🕵️ 评审了最多来自他人的 Pull Requests,他们保证了代码、文档尤其是 **翻译** 的质量。
-
-{% if people %}
-
-{% for user in people.top_reviewers %}
-
-
-{% endfor %}
-
-
-{% endif %}
-
-## 赞助商
-
-以下是 **赞助商** 。😎
-
-他们主要通过
GitHub Sponsors支持我在 **FastAPI** (和其他项目)的工作。
-
-{% if sponsors.gold %}
-
-### 金牌赞助商
-
-{% for sponsor in sponsors.gold -%}
-

-{% endfor %}
-{% endif %}
-
-{% if sponsors.silver %}
-
-### 银牌赞助商
-
-{% for sponsor in sponsors.silver -%}
-

-{% endfor %}
-{% endif %}
-
-{% if sponsors.bronze %}
-
-### 铜牌赞助商
-
-{% for sponsor in sponsors.bronze -%}
-

-{% endfor %}
-{% endif %}
-
-### 个人赞助
-
-{% if github_sponsors %}
-{% for group in github_sponsors.sponsors %}
-
-
-
-{% for user in group %}
-{% if user.login not in sponsors_badge.logins %}
-
-
-
-{% endif %}
-{% endfor %}
-
-
-
-{% endfor %}
-{% endif %}
-
-## 关于数据 - 技术细节
-
-该页面的目的是突出社区为帮助他人而付出的努力。
-
-尤其是那些不引人注目且涉及更困难的任务,例如帮助他人解决问题或者评审翻译 Pull Requests。
-
-该数据每月计算一次,您可以阅读
源代码。
-
-这里也强调了赞助商的贡献。
-
-我也保留更新算法,栏目,统计阈值等的权利(以防万一🤷)。
diff --git a/docs/zh/docs/features.md b/docs/zh/docs/features.md
index 4752947a3..24dc3e8ce 100644
--- a/docs/zh/docs/features.md
+++ b/docs/zh/docs/features.md
@@ -65,10 +65,13 @@ my_second_user: User = User(**second_user_data)
```
-!!! info
- `**second_user_data` 意思是:
+/// info
- 直接将`second_user_data`字典的键和值直接作为key-value参数传递,等同于:`User(id=4, name="Mary", joined="2018-11-30")`
+`**second_user_data` 意思是:
+
+直接将`second_user_data`字典的键和值直接作为key-value参数传递,等同于:`User(id=4, name="Mary", joined="2018-11-30")`
+
+///
### 编辑器支持
@@ -171,7 +174,7 @@ FastAPI 有一个使用非常简单,但是非常强大的
Pydantic 完全兼容(并基于)。所以,你有的其他的 Pydantic 代码也能正常工作。
+**FastAPI** 和 Pydantic 完全兼容(并基于)。所以,你有的其他的 Pydantic 代码也能正常工作。
兼容包括基于 Pydantic 的外部库, 例如用与数据库的 ORMs, ODMs。
@@ -193,9 +196,7 @@ FastAPI 有一个使用非常简单,但是非常强大的 发布和 **FastAPI** 有关的推特 让我和其他人知道你为什么喜欢它。
+* 在 **GitHub** 上关注我
+ * 了解其它我创建的开源项目,或许对您会有帮助
+ * 关注我什么时候创建新的开源项目
+* 在 **Twitter** 上关注我
+ * 告诉我您使用 FastAPI(我非常乐意听到这种消息)
+ * 接收我发布公告或新工具的消息
+ * 您还可以关注@fastapi on Twitter,这是个独立的账号
+* 在**领英**上联系我
+ * 接收我发布公告或新工具的消息(虽然我用 Twitter 比较多)
+* 阅读我在 **Dev.to** 或 **Medium** 上的文章,或关注我
+ * 阅读我的其它想法、文章,了解我创建的工具
+ * 关注我,这样就可以随时看到我发布的新文章
-## 告诉我你正在如何使用 **FastAPI**
+## Tweet about **FastAPI**
-我很乐意听到有关 **FastAPI** 被如何使用、你喜欢它的哪一点、被投入使用的项目/公司等等信息。
+Tweet about **FastAPI** 让我和大家知道您为什么喜欢 FastAPI。🎉
-你可以通过以下平台让我知道:
-
-* **Twitter**。
-* **Linkedin**。
-* **Medium**。
+知道有人使用 **FastAPI**,我会很开心,我也想知道您为什么喜欢 FastAPI,以及您在什么项目/哪些公司使用 FastAPI,等等。
## 为 FastAPI 投票
-* 在 Slant 上为 **FastAPI** 投票。
+* 在 Slant 上为 **FastAPI** 投票
+* 在 AlternativeTo 上为 **FastAPI** 投票
+
+## 在 GitHub 上帮助其他人解决问题
+
+您可以查看现有 issues,并尝试帮助其他人解决问题,说不定您能解决这些问题呢。🤓
+
+如果帮助很多人解决了问题,您就有可能成为 [FastAPI 的官方专家](fastapi-people.md#_3){.internal-link target=_blank}。🎉
+
+## 监听 GitHub 资源库
+
+您可以在 GitHub 上「监听」FastAPI(点击右上角的 "watch" 按钮): https://github.com/fastapi/fastapi. 👀
+
+如果您选择 "Watching" 而不是 "Releases only",有人创建新 Issue 时,您会接收到通知。
+
+然后您就可以尝试并帮助他们解决问题。
+
+## 创建 Issue
+
+您可以在 GitHub 资源库中创建 Issue,例如:
-## 帮助他人解决 GitHub 的 issues
+* 提出**问题**或**意见**
+* 提出新**特性**建议
-你可以查看 已有的 issues 并尝试帮助其他人。
+**注意**:如果您创建 Issue,我会要求您也要帮助别的用户。😉
-## Watch GitHub 仓库
+## 创建 PR
-你可以在 GitHub 上 "watch" FastAPI(点击右上角的 "watch" 按钮):https://github.com/tiangolo/fastapi。
+您可以创建 PR 为源代码做[贡献](contributing.md){.internal-link target=_blank},例如:
-如果你选择的是 "Watching" 而不是 "Releases only" 选项,你会在其他人创建了新的 issue 时收到通知。
+* 修改文档错别字
+* 编辑这个文件,分享 FastAPI 的文章、视频、博客,不论是您自己的,还是您看到的都成
+ * 注意,添加的链接要放在对应区块的开头
+* [翻译文档](contributing.md#_8){.internal-link target=_blank}
+ * 审阅别人翻译的文档
+* 添加新的文档内容
+* 修复现有问题/Bug
+* 添加新功能
-然后你可以尝试帮助他们解决这些 issue。
+## 加入聊天
-## 创建 issue
+快加入 👥 Discord 聊天服务器 👥 和 FastAPI 社区里的小伙伴一起哈皮吧。
-你可以在 GitHub 仓库中 创建一个新 issue 用来:
+/// tip | 提示
-* 报告 bug 或问题。
-* 提议新的特性。
-* 提问。
+如有问题,请在 GitHub Issues 里提问,在这里更容易得到 [FastAPI 专家](fastapi-people.md#_3){.internal-link target=_blank}的帮助。
-## 创建 Pull Request
+聊天室仅供闲聊。
-你可以 创建一个 Pull Request 用来:
+///
-* 纠正你在文档中发现的错别字。
-* 添加新的文档内容。
-* 修复已有的 bug 或问题。
-* 添加新的特性。
+### 别在聊天室里提问
+
+注意,聊天室更倾向于“闲聊”,经常有人会提出一些笼统得让人难以回答的问题,所以在这里提问一般没人回答。
+
+GitHub Issues 里提供了模板,指引您提出正确的问题,有利于获得优质的回答,甚至可能解决您还没有想到的问题。而且就算答疑解惑要耗费不少时间,我还是会尽量在 GitHub 里回答问题。但在聊天室里,我就没功夫这么做了。😅
+
+聊天室里的聊天内容也不如 GitHub 里好搜索,聊天里的问答很容易就找不到了。只有在 GitHub Issues 里的问答才能帮助您成为 [FastAPI 专家](fastapi-people.md#_3){.internal-link target=_blank},在 GitHub Issues 中为您带来更多关注。
+
+另一方面,聊天室里有成千上万的用户,在这里,您有很大可能遇到聊得来的人。😄
## 赞助作者
-你还可以通过 GitHub sponsors 在经济上支持作者(我)。
+您还可以通过 GitHub 赞助商资助本项目的作者(就是我)。
+
+给我买杯咖啡 ☕️ 以示感谢 😄
+
+当然您也可以成为 FastAPI 的金牌或银牌赞助商。🏅🎉
+
+## 赞助 FastAPI 使用的工具
+
+如您在本文档中所见,FastAPI 站在巨人的肩膀上,它们分别是 Starlette 和 Pydantic。
+
+您还可以赞助:
-这样你可以给我买杯咖啡☕️以示谢意😄。
+* Samuel Colvin (Pydantic)
+* Encode (Starlette, Uvicorn)
---
-感谢!
+谢谢!🚀
diff --git a/docs/zh/docs/history-design-future.md b/docs/zh/docs/history-design-future.md
new file mode 100644
index 000000000..48cfef524
--- /dev/null
+++ b/docs/zh/docs/history-design-future.md
@@ -0,0 +1,78 @@
+# 历史、设计、未来
+
+不久前,曾有 **FastAPI** 用户问过:
+
+> 这个项目有怎样的历史?好像它只用了几周就从默默无闻变得众所周知……
+
+在此,我们简单回顾一下 **FastAPI** 的历史。
+
+## 备选方案
+
+有那么几年,我曾领导数个开发团队为诸多复杂需求创建各种 API,这些需求包括机器学习、分布系统、异步任务、NoSQL 数据库等领域。
+
+作为工作的一部分,我需要调研很多备选方案、还要测试并且使用这些备选方案。
+
+**FastAPI** 其实只是延续了这些前辈的历史。
+
+正如[备选方案](alternatives.md){.internal-link target=_blank}一章所述:
+
+
+没有大家之前所做的工作,**FastAPI** 就不会存在。
+
+以前创建的这些工具为它的出现提供了灵感。
+
+在那几年中,我一直回避创建新的框架。首先,我尝试使用各种框架、插件、工具解决 **FastAPI** 现在的功能。
+
+但到了一定程度之后,我别无选择,只能从之前的工具中汲取最优思路,并以尽量好的方式把这些思路整合在一起,使用之前甚至是不支持的语言特性(Python 3.6+ 的类型提示),从而创建一个能满足我所有需求的框架。
+
+
+
+## 调研
+
+通过使用之前所有的备选方案,我有机会从它们之中学到了很多东西,获取了很多想法,并以我和我的开发团队能想到的最好方式把这些思路整合成一体。
+
+例如,大家都清楚,在理想状态下,它应该基于标准的 Python 类型提示。
+
+而且,最好的方式是使用现有的标准。
+
+因此,甚至在开发 **FastAPI** 前,我就花了几个月的时间研究 OpenAPI、JSON Schema、OAuth2 等规范。深入理解它们之间的关系、重叠及区别之处。
+
+## 设计
+
+然后,我又花了一些时间从用户角度(使用 FastAPI 的开发者)设计了开发者 **API**。
+
+同时,我还在最流行的 Python 代码编辑器中测试了很多思路,包括 PyCharm、VS Code、基于 Jedi 的编辑器。
+
+根据最新 Python 开发者调研报告显示,这几种编辑器覆盖了约 80% 的用户。
+
+也就是说,**FastAPI** 针对差不多 80% 的 Python 开发者使用的编辑器进行了测试,而且其它大多数编辑器的工作方式也与之类似,因此,**FastAPI** 的优势几乎能在所有编辑器上体现。
+
+通过这种方式,我就能找到尽可能减少代码重复的最佳方式,进而实现处处都有自动补全、类型提示与错误检查等支持。
+
+所有这些都是为了给开发者提供最佳的开发体验。
+
+## 需求项
+
+经过测试多种备选方案,我最终决定使用 **Pydantic**,并充分利用它的优势。
+
+我甚至为它做了不少贡献,让它完美兼容了 JSON Schema,支持多种方式定义约束声明,并基于多个编辑器,改进了它对编辑器支持(类型检查、自动补全)。
+
+在开发期间,我还为 **Starlette** 做了不少贡献,这是另一个关键需求项。
+
+## 开发
+
+当我启动 **FastAPI** 开发的时候,绝大多数部件都已经就位,设计已经定义,需求项和工具也已经准备就绪,相关标准与规范的知识储备也非常清晰而新鲜。
+
+## 未来
+
+至此,**FastAPI** 及其理念已经为很多人所用。
+
+对于很多用例,它比以前很多备选方案都更适用。
+
+很多开发者和开发团队已经依赖 **FastAPI** 开发他们的项目(包括我和我的团队)。
+
+但,**FastAPI** 仍有很多改进的余地,也还需要添加更多的功能。
+
+总之,**FastAPI** 前景光明。
+
+在此,我们衷心感谢[您的帮助](help-fastapi.md){.internal-link target=_blank}。
diff --git a/docs/zh/docs/how-to/configure-swagger-ui.md b/docs/zh/docs/how-to/configure-swagger-ui.md
new file mode 100644
index 000000000..108e0cb95
--- /dev/null
+++ b/docs/zh/docs/how-to/configure-swagger-ui.md
@@ -0,0 +1,70 @@
+# 配置 Swagger UI
+
+你可以配置一些额外的 Swagger UI 参数.
+
+如果需要配置它们,可以在创建 `FastAPI()` 应用对象时或调用 `get_swagger_ui_html()` 函数时传递 `swagger_ui_parameters` 参数。
+
+`swagger_ui_parameters` 接受一个直接传递给 Swagger UI的字典,包含配置参数键值对。
+
+FastAPI会将这些配置转换为 **JSON**,使其与 JavaScript 兼容,因为这是 Swagger UI 需要的。
+
+## 不使用语法高亮
+
+比如,你可以禁用 Swagger UI 中的语法高亮。
+
+当没有改变设置时,语法高亮默认启用:
+
+
+
+但是你可以通过设置 `syntaxHighlight` 为 `False` 来禁用 Swagger UI 中的语法高亮:
+
+{* ../../docs_src/configure_swagger_ui/tutorial001.py hl[3] *}
+
+...在此之后,Swagger UI 将不会高亮代码:
+
+
+
+## 改变主题
+
+同样地,你也可以通过设置键 `"syntaxHighlight.theme"` 来设置语法高亮主题(注意中间有一个点):
+
+{* ../../docs_src/configure_swagger_ui/tutorial002.py hl[3] *}
+
+这个配置会改变语法高亮主题:
+
+
+
+## 改变默认 Swagger UI 参数
+
+FastAPI 包含了一些默认配置参数,适用于大多数用例。
+
+其包括这些默认配置参数:
+
+{* ../../fastapi/openapi/docs.py ln[7:23] *}
+
+你可以通过在 `swagger_ui_parameters` 中设置不同的值来覆盖它们。
+
+比如,如果要禁用 `deepLinking`,你可以像这样传递设置到 `swagger_ui_parameters` 中:
+
+{* ../../docs_src/configure_swagger_ui/tutorial003.py hl[3] *}
+
+## 其他 Swagger UI 参数
+
+查看其他 Swagger UI 参数,请阅读 docs for Swagger UI parameters。
+
+## JavaScript-only 配置
+
+Swagger UI 同样允许使用 **JavaScript-only** 配置对象(例如,JavaScript 函数)。
+
+FastAPI 包含这些 JavaScript-only 的 `presets` 设置:
+
+```JavaScript
+presets: [
+ SwaggerUIBundle.presets.apis,
+ SwaggerUIBundle.SwaggerUIStandalonePreset
+]
+```
+
+这些是 **JavaScript** 对象,而不是字符串,所以你不能直接从 Python 代码中传递它们。
+
+如果你需要像这样使用 JavaScript-only 配置,你可以使用上述方法之一。覆盖所有 Swagger UI *path operation* 并手动编写任何你需要的 JavaScript。
diff --git a/docs/zh/docs/how-to/general.md b/docs/zh/docs/how-to/general.md
new file mode 100644
index 000000000..e8b6dd3b2
--- /dev/null
+++ b/docs/zh/docs/how-to/general.md
@@ -0,0 +1,39 @@
+# 通用 - 如何操作 - 诀窍
+
+这里是一些指向文档中其他部分的链接,用于解答一般性或常见问题。
+
+## 数据过滤 - 安全性
+
+为确保不返回超过需要的数据,请阅读 [教程 - 响应模型 - 返回类型](../tutorial/response-model.md){.internal-link target=_blank} 文档。
+
+## 文档的标签 - OpenAPI
+
+在文档界面中添加**路径操作**的标签和进行分组,请阅读 [教程 - 路径操作配置 - Tags 参数](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank} 文档。
+
+## 文档的概要和描述 - OpenAPI
+
+在文档界面中添加**路径操作**的概要和描述,请阅读 [教程 - 路径操作配置 - Summary 和 Description 参数](../tutorial/path-operation-configuration.md#summary-description){.internal-link target=_blank} 文档。
+
+## 文档的响应描述 - OpenAPI
+
+在文档界面中定义并显示响应描述,请阅读 [教程 - 路径操作配置 - 响应描述](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank} 文档。
+
+## 文档弃用**路径操作** - OpenAPI
+
+在文档界面中显示弃用的**路径操作**,请阅读 [教程 - 路径操作配置 - 弃用](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank} 文档。
+
+## 将任何数据转换为 JSON 兼容格式
+
+要将任何数据转换为 JSON 兼容格式,请阅读 [教程 - JSON 兼容编码器](../tutorial/encoder.md){.internal-link target=_blank} 文档。
+
+## OpenAPI 元数据 - 文档
+
+要添加 OpenAPI 的元数据,包括许可证、版本、联系方式等,请阅读 [教程 - 元数据和文档 URL](../tutorial/metadata.md){.internal-link target=_blank} 文档。
+
+## OpenAPI 自定义 URL
+
+要自定义 OpenAPI 的 URL(或删除它),请阅读 [教程 - 元数据和文档 URL](../tutorial/metadata.md#openapi-url){.internal-link target=_blank} 文档。
+
+## OpenAPI 文档 URL
+
+要更改用于自动生成文档的 URL,请阅读 [教程 - 元数据和文档 URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}.
diff --git a/docs/zh/docs/how-to/index.md b/docs/zh/docs/how-to/index.md
new file mode 100644
index 000000000..ac097618b
--- /dev/null
+++ b/docs/zh/docs/how-to/index.md
@@ -0,0 +1,13 @@
+# 如何操作 - 诀窍
+
+在这里,你将看到关于**多个主题**的不同诀窍或“如何操作”指南。
+
+这些方法多数是**相互独立**的,在大多数情况下,你只需在这些内容适用于**你的项目**时才需要学习它们。
+
+如果某些内容看起来对你的项目有用,请继续查阅,否则请直接跳过它们。
+
+/// tip | 小技巧
+
+如果你想以系统的方式**学习 FastAPI**(推荐),请阅读 [教程 - 用户指南](../tutorial/index.md){.internal-link target=_blank} 的每一章节。
+
+///
diff --git a/docs/zh/docs/index.md b/docs/zh/docs/index.md
index 85707e573..94cf8745c 100644
--- a/docs/zh/docs/index.md
+++ b/docs/zh/docs/index.md
@@ -1,3 +1,9 @@
+# FastAPI
+
+
+
@@ -5,30 +11,33 @@
FastAPI 框架,高性能,易于学习,高效编码,生产可用
-
-
+
+
-
-
+
+
+
+
+
---
**文档**: https://fastapi.tiangolo.com
-**源码**: https://github.com/tiangolo/fastapi
+**源码**: https://github.com/fastapi/fastapi
---
-FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 3.6+ 并基于标准的 Python 类型提示。
+FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 并基于标准的 Python 类型提示。
关键特性:
-* **快速**:可与 **NodeJS** 和 **Go** 比肩的极高性能(归功于 Starlette 和 Pydantic)。[最快的 Python web 框架之一](#_11)。
+* **快速**:可与 **NodeJS** 和 **Go** 并肩的极高性能(归功于 Starlette 和 Pydantic)。[最快的 Python web 框架之一](#_11)。
* **高效编码**:提高功能开发速度约 200% 至 300%。*
* **更少 bug**:减少约 40% 的人为(开发者)导致错误。*
@@ -61,7 +70,7 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框
「_[...] 最近我一直在使用 **FastAPI**。[...] 实际上我正在计划将其用于我所在的**微软**团队的所有**机器学习服务**。其中一些服务正被集成进核心 **Windows** 产品和一些 **Office** 产品。_」
-
+
---
@@ -85,7 +94,7 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框
「_老实说,你的作品看起来非常可靠和优美。在很多方面,这就是我想让 **Hug** 成为的样子 - 看到有人实现了它真的很鼓舞人心。_」
-
+
---
@@ -107,12 +116,12 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框
## 依赖
-Python 3.6 及更高版本
+Python 及更高版本
FastAPI 站在以下巨人的肩膀之上:
* Starlette 负责 web 部分。
-* Pydantic 负责数据部分。
+* Pydantic 负责数据部分。
## 安装
@@ -126,12 +135,12 @@ $ pip install fastapi
-你还会需要一个 ASGI 服务器,生产环境可以使用
```console
-$ pip install fastapi[all]
+$ pip install "fastapi[standard]"
---> 100%
```
-......以上安装还包括了 `uvicorn`,你可以将其用作运行代码的服务器。
-
-!!! note
- 你也可以分开来安装。
-
- 假如你想将应用程序部署到生产环境,你可能要执行以下操作:
-
- ```
- pip install fastapi
- ```
+/// note
- 并且安装`uvicorn`来作为服务器:
+当您使用 `pip install "fastapi[standard]"` 进行安装时,它会附带一些默认的可选标准依赖项。
- ```
- pip install uvicorn[standard]
- ```
+如果您不想安装这些可选依赖,可以选择安装 `pip install fastapi`。
- 然后对你想使用的每个可选依赖项也执行相同的操作。
+///
## 进阶用户指南
-在本**教程-用户指南**之后,你可以阅读**进阶用户指南**。
+在本**教程-用户指南**之后,您可以阅读**进阶用户指南**。
**进阶用户指南**以本教程为基础,使用相同的概念,并教授一些额外的特性。
-但是你应该先阅读**教程-用户指南**(即你现在正在阅读的内容)。
+但是您应该先阅读**教程-用户指南**(即您现在正在阅读的内容)。
-教程经过精心设计,使你可以仅通过**教程-用户指南**来开发一个完整的应用程序,然后根据你的需要,使用**进阶用户指南**中的一些其他概念,以不同的方式来扩展它。
+教程经过精心设计,使您可以仅通过**教程-用户指南**来开发一个完整的应用程序,然后根据您的需要,使用**进阶用户指南**中的一些其他概念,以不同的方式来扩展它。
diff --git a/docs/zh/docs/tutorial/metadata.md b/docs/zh/docs/tutorial/metadata.md
index 3e669bc72..d29a1e6d0 100644
--- a/docs/zh/docs/tutorial/metadata.md
+++ b/docs/zh/docs/tutorial/metadata.md
@@ -1,105 +1,100 @@
-# 元数据和文档 URL
-
-你可以在 **FastAPI** 应用中自定义几个元数据配置。
-
-## 标题、描述和版本
-
-你可以设定:
-
-* **Title**:在 OpenAPI 和自动 API 文档用户界面中作为 API 的标题/名称使用。
-* **Description**:在 OpenAPI 和自动 API 文档用户界面中用作 API 的描述。
-* **Version**:API 版本,例如 `v2` 或者 `2.5.0`。
- * 如果你之前的应用程序版本也使用 OpenAPI 会很有用。
-
-使用 `title`、`description` 和 `version` 来设置它们:
-
-```Python hl_lines="4-6"
-{!../../../docs_src/metadata/tutorial001.py!}
-```
-
-通过这样设置,自动 API 文档看起来会像:
-
-
```console
-$ pip install python-jose[cryptography]
+$ pip install pyjwt
---> 100%
```
-
+
+```console
+$ pytest
+
+================ test session starts ================
+platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
+rootdir: /home/user/code/superawesome-cli/app
+plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1
+collected 6 items
+
+---> 100%
+
+test_main.py ...... [100%]
+
+================= 1 passed in 0.03s =================
+```
+
+
diff --git a/docs/zh/docs/virtual-environments.md b/docs/zh/docs/virtual-environments.md
new file mode 100644
index 000000000..9b3c0340a
--- /dev/null
+++ b/docs/zh/docs/virtual-environments.md
@@ -0,0 +1,844 @@
+# 虚拟环境
+
+当你在 Python 工程中工作时,你可能会有必要用到一个**虚拟环境**(或类似的机制)来隔离你为每个工程安装的包。
+
+/// info
+
+如果你已经了解虚拟环境,知道如何创建和使用它们,你可以考虑跳过这一部分。🤓
+
+///
+
+/// tip
+
+**虚拟环境**和**环境变量**是不同的。
+
+**环境变量**是系统中的一个变量,可以被程序使用。
+
+**虚拟环境**是一个包含一些文件的目录。
+
+///
+
+/// info
+
+这个页面将教你如何使用**虚拟环境**以及了解它们的工作原理。
+
+如果你计划使用一个**可以为你管理一切的工具**(包括安装 Python),试试
+
+```console
+// 进入主目录
+$ cd
+// 创建一个用于存放所有代码工程的目录
+$ mkdir code
+// 进入 code 目录
+$ cd code
+// 创建一个用于存放这个工程的目录
+$ mkdir awesome-project
+// 进入这个工程的目录
+$ cd awesome-project
+```
+
+
+
+## 创建一个虚拟环境
+
+在开始一个 Python 工程的**第一时间**,**
+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+
+
+如果它显示了在你工程 (在这个例子中是 `awesome-project`) 的 `.venv/bin/python` 中的 `python` 二进制文件,那么它就生效了。🎉
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ Get-Command python
+
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+
+
+如果它显示了在你工程 (在这个例子中是 `awesome-project`) 的 `.venv\Scripts\python` 中的 `python` 二进制文件,那么它就生效了。🎉
+
+////
+
+## 升级 `pip`
+
+/// tip
+
+如果你使用
+
+```console
+// 先别去运行这个命令,这只是一个示例 🤓
+$ pip install "fastapi[standard]"
+---> 100%
+```
+
+
+
+这将会从
+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+$ Get-Command python
+
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+
+
+////
+
+这意味着将使用的 `python` 程序是**在虚拟环境中**的那个。
+
+在 Linux 和 macOS 中使用 `which`,在 Windows PowerShell 中使用 `Get-Command`。
+
+这个命令的工作方式是,它会在 `PATH` 环境变量中查找,按顺序**逐个路径**查找名为 `python` 的程序。一旦找到,它会**显示该程序的路径**。
+
+最重要的部分是,当你调用 `python` 时,将执行的就是这个确切的 "`python`"。
+
+因此,你可以确认你是否在正确的虚拟环境中。
+
+/// tip
+
+激活一个虚拟环境,获取一个 Python,然后**转到另一个工程**是一件很容易的事情;
+
+但如果第二个工程**无法工作**,那是因为你使用了来自另一个工程的虚拟环境的、**不正确的 Python**。
+
+因此,会检查正在使用的 `python` 是很有用的。🤓
+
+///
+
+## 为什么要停用虚拟环境
+
+例如,你可能正在一个工程 `philosophers-stone` 上工作,**激活了该虚拟环境**,安装了包并使用了该环境,
+
+然后你想要在**另一个工程** `prisoner-of-azkaban` 上工作,
+
+你进入那个工程:
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+
+$ python main.py
+
+// 导入 sirius 报错,它没有安装 😱
+Traceback (most recent call last):
+ File "main.py", line 1, in
+ import sirius
+```
+
+
+
+但是如果你停用虚拟环境并激活 `prisoner-of-askaban` 的新虚拟环境,那么当你运行 `python` 时,它会使用 `prisoner-of-askaban` 中的虚拟环境中的 Python。
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+
+// 你不需要在旧目录中操作停用,你可以在任何地方操作停用,甚至在转到另一个工程之后 😎
+$ deactivate
+
+// 激活 prisoner-of-azkaban/.venv 中的虚拟环境 🚀
+$ source .venv/bin/activate
+
+// 现在当你运行 python 时,它会在这个虚拟环境中找到安装的 sirius 包 ✨
+$ python main.py
+
+I solemnly swear 🐺
+```
+
+
+
+## 替代方案
+
+这是一个简单的指南,可以帮助你入门并教会你如何理解一切**底层**的东西。
+
+有许多**替代方案**来管理虚拟环境、包依赖(requirements)、工程。
+
+一旦你准备好并想要使用一个工具来**管理整个工程**、包依赖、虚拟环境等,建议你尝试