+
+```console
+// আপনি চাইলে MY_NAME নামে একটি env var তৈরি করতে পারেন
+$ export MY_NAME="Wade Wilson"
+
+// তারপরে এটিকে চাইলে অন্যান্য প্রোগ্রামে ব্যবহার করতে পারেন
+$ echo "Hello $MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+//// tab | উইন্ডোজ পাওয়ারশেল
+
+
+
+```console
+// MY_NAME নামে env var তৈরি
+$ $Env:MY_NAME = "Wade Wilson"
+
+// অন্যান্য প্রোগ্রামে এটিকে ব্যবহার
+$ echo "Hello $Env:MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+## পাইথনে env vars রিড করা
+
+আপনি চাইলে পাইথনের **বাইরে**, টার্মিনালে (বা অন্য কোনো উপায়ে) এনভায়রনমেন্ট ভেরিয়েবলস তৈরি করতে পারেন, এবং পরে সেগুলো **পাইথনে রিড** (অ্যাক্সেস করতে) পারেন।
+
+উদাহরণস্বরূপ, আপনার `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"` ব্যবহার করেছি।
+
+///
+
+তারপরে পাইথন প্রোগ্রামটিকে নিম্নোক্তভাবে কল করা যাবেঃ
+
+//// tab | লিনাক্স, ম্যাকওএস, উইন্ডোজ Bash
+
+
+
+```console
+// এখনো আমরা এনভায়রনমেন্ট ভেরিয়েবল সেট করিনি
+$ python main.py
+
+// যেহেতু env var সেট করা হয়নি, তাই আমরা ডিফল্ট ভ্যালু পাচ্ছি
+
+Hello World from Python
+
+// কিন্তু আমরা প্রথমে যদি একটা এনভায়রনমেন্ট ভারিয়েবল তৈরি করে নেই
+$ export MY_NAME="Wade Wilson"
+
+// এবং তারপর আবার প্রোগ্রাটিকে কল করি
+$ python main.py
+
+// এখন এটি এনভায়রনমেন্ট ভেরিয়েবল রিড করতে পারবে
+
+Hello Wade Wilson from Python
+```
+
+
+
+////
+
+//// tab | উইন্ডোজ পাওয়ারশেল
+
+
+
+```console
+// এখনো আমরা এনভায়রনমেন্ট ভেরিয়েবল সেট করিনি
+$ python main.py
+
+// যেহেতু env var সেট করা হয়নি, তাই আমরা ডিফল্ট ভ্যালু পাচ্ছি
+
+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: Config।
+
+///
+
+## টাইপস এবং ভ্যালিডেশন
+
+এই এনভায়রনমেন্ট ভেরিয়েবলগুলো শুধুমাত্র **টেক্সট স্ট্রিংস** হ্যান্ডেল করতে পারে, যেহেতু এগুলো পাইথনের বাইরে অবস্থিত এবং অন্যান্য প্রোগ্রাম এবং সিস্টেমের বাকি অংশের (এমনকি বিভিন্ন অপারেটিং সিস্টেম যেমন লিনাক্স, উইন্ডোজ, ম্যাকওএস) সাথে সামঞ্জস্যপূর্ণ হতে হয়।
+
+এর অর্থ হচ্ছে পাইথনে এনভায়রনমেন্ট ভেরিয়েবল থেকে রিড করা **যেকোনো ভ্যালু** একটি `str` হবে, এবং অন্য কোনো টাইপে কনভার্সন বা যেকোনো ভেলিডেশন কোডে আলাদাভাবে করতে হবে।
+
+এনভায়রনমেন্ট ভেরিয়েবল ব্যবহার করে **এপ্লিকেশন সেটিংস** হ্যান্ডেল করা নিয়ে আরো বিস্তারিত জানা যাবে [Advanced User Guide - Settings and Environment Variables](./advanced/settings.md){.internal-link target=_blank}.
+
+## `PATH` এনভায়রনমেন্ট ভেরিয়েবল
+
+**`PATH`** নামে একটি **বিশেষ** এনভায়রনমেন্ট ভেরিয়েবল রয়েছে, যেটি প্রোগ্রাম রান করার জন্য অপারেটিং সিস্টেমস (লিনাক্স, ম্যাকওএস, উইন্ডোজ) দ্বারা ব্যবহৃত হয়।
+
+`PATH` ভেরিয়েবল এর ভ্যালু হচ্ছে একটি বিশাল স্ট্রিং যা ডিরেক্টরিকে কোলন `:` দিয়ে আলাদা করার মাধ্যমে লিনাক্সে ও ম্যাকওএস এ, এবং সেমিকোলন `;` এর মাধ্যমে উইন্ডোজ এ তৈরি করা থাকে।
+
+উদাহরণস্বরূপ, `PATH` ভেরিয়েবল নিচের মতো দেখতে হতে পারেঃ
+
+//// tab | লিনাক্স, ম্যাকওএস
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
+```
+
+তারমানে হলো সিস্টেম প্রোগ্রামগুলোকে নিচের ডিরেক্টরিগুলোতে খুঁজবেঃ
+
+* `/usr/local/bin`
+* `/usr/bin`
+* `/bin`
+* `/usr/sbin`
+* `/sbin`
+
+////
+
+//// tab | উইন্ডোজ
+
+```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` নামের একটি প্রোগ্রাম খুঁজবে।
+
+যদি এটি খুঁজে পায়, তাহলে এটি প্রোগ্রামটিকে ব্যবহার করবে। অন্যথায় এটি **অন্যান্য ডিরেক্টরিগুলোতে** এটিকে খুঁজতে থাকবে।
+
+### পাইথন ইনস্টল এবং `PATH` আপডেট
+
+যখন আপনি পাইথন ইনস্টল করেন, আপনি `PATH` এনভায়রনমেন্ট ভেরিয়েবল আপডেট করতে চান কিনা সেটা জিজ্ঞেস করা হতে পারে।
+
+//// tab | লিনাক্স, ম্যাকওএস
+
+ধরা যাক আপনি পাইথন ইনস্টল করলেন এবং এটি `/opt/custompython/bin` ডিরেক্টরিতে ইনস্টল হচ্ছে।
+
+যদি আপনি "Yes" সিলেক্ট করে `PATH` এনভায়রনমেন্ট ভেরিয়েবল আপডেট করতে চান, তাহলে ইনস্টলার `/opt/custompython/bin` কে `PATH` এনভায়রনমেন্ট ভেরিয়েবল এ এড করে দিবে।
+
+এটা দেখতে এমনটা হতে পারেঃ
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin
+```
+
+এইভাবে, আপনি যখন টার্মিনালে `python` টাইপ করেন, সিস্টেম পাইথন প্রোগ্রামটিকে `/opt/custompython/bin` (সর্বশেষ ডিরেক্টরি) তে খুঁজে পাবে এবং এটাকে ব্যবহার করবে।
+
+////
+
+//// tab | উইন্ডোজ
+
+ধরা যাক আপনি পাইথন ইনস্টল করলেন এবং এটি `C:\opt\custompython\bin` ডিরেক্টরিতে ইনস্টল হচ্ছে।
+
+যদি আপনি "Yes" সিলেক্ট করে `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` (সর্বশেষ ডিরেক্টরি) তে খুঁজে পাবে এবং এটাকে ব্যবহার করবে।
+
+////
+
+তাই, আপনি যদি টাইপ করেনঃ
+
+
+
+```console
+$ python
+```
+
+
+
+//// tab | লিনাক্স, ম্যাকওএস
+
+সিস্টেম `python` প্রোগ্রামকে `/opt/custompython/bin` এ **খুঁজে পাবে** এবং এটাকে রান করবে।
+
+এটা মোটামুটিভাবে নিচের মতো করে লেখার সমান হবেঃ
+
+
{% endblock %}
diff --git a/docs/es/docs/deployment/concepts.md b/docs/es/docs/deployment/concepts.md
index f5725c5dc..bcc7948bc 100644
--- a/docs/es/docs/deployment/concepts.md
+++ b/docs/es/docs/deployment/concepts.md
@@ -216,7 +216,7 @@ Este Proceso Administrador probablemente sería el que escuche en el **puerto**
Esos worker processes serían los que ejecutan tu aplicación, realizarían los cálculos principales para recibir un **request** y devolver un **response**, y cargarían cualquier cosa que pongas en variables en RAM.
-
+
Y por supuesto, la misma máquina probablemente tendría **otros procesos** ejecutándose también, aparte de tu aplicación.
diff --git a/docs/es/docs/deployment/docker.md b/docs/es/docs/deployment/docker.md
index ff204f078..3a39d3661 100644
--- a/docs/es/docs/deployment/docker.md
+++ b/docs/es/docs/deployment/docker.md
@@ -6,7 +6,7 @@ Usar contenedores de Linux tiene varias ventajas, incluyendo **seguridad**, **re
/// tip | Consejo
-¿Tienes prisa y ya conoces esto? Salta al [`Dockerfile` más abajo 👇](#build-a-docker-image-for-fastapi).
+¿Tienes prisa y ya conoces esto? Salta al [`Dockerfile` más abajo 👇](#construir-una-imagen-de-docker-para-fastapi).
///
diff --git a/docs/es/docs/deployment/https.md b/docs/es/docs/deployment/https.md
index f2871ac03..3ccb5dc47 100644
--- a/docs/es/docs/deployment/https.md
+++ b/docs/es/docs/deployment/https.md
@@ -85,7 +85,7 @@ Primero, el navegador consultaría con los **servidores DNS** cuál es la **IP d
Los servidores DNS le dirían al navegador que use una **dirección IP** específica. Esa sería la dirección IP pública utilizada por tu servidor, que configuraste en los servidores DNS.
-
+
### Inicio del Handshake TLS
@@ -93,7 +93,7 @@ El navegador luego se comunicaría con esa dirección IP en el **puerto 443** (e
La primera parte de la comunicación es solo para establecer la conexión entre el cliente y el servidor y decidir las claves criptográficas que usarán, etc.
-
+
Esta interacción entre el cliente y el servidor para establecer la conexión TLS se llama **handshake TLS**.
@@ -111,7 +111,7 @@ Usando la **extensión SNI** discutida anteriormente, el TLS Termination Proxy v
En este caso, usaría el certificado para `someapp.example.com`.
-
+
El cliente ya **confía** en la entidad que generó ese certificado TLS (en este caso Let's Encrypt, pero lo veremos más adelante), por lo que puede **verificar** que el certificado sea válido.
@@ -133,19 +133,19 @@ Ahora que el cliente y el servidor (específicamente el navegador y el TLS Termi
Así que, el cliente envía un **request HTTPS**. Esto es simplemente un request HTTP a través de una conexión TLS encriptada.
-
+
### Desencriptar el Request
El TLS Termination Proxy usaría la encriptación acordada para **desencriptar el request**, y transmitiría el **request HTTP simple (desencriptado)** al proceso que ejecuta la aplicación (por ejemplo, un proceso con Uvicorn ejecutando la aplicación FastAPI).
-
+
### Response HTTP
La aplicación procesaría el request y enviaría un **response HTTP simple (sin encriptar)** al TLS Termination Proxy.
-
+
### Response HTTPS
@@ -153,7 +153,7 @@ El TLS Termination Proxy entonces **encriptaría el response** usando la criptog
Luego, el navegador verificaría que el response sea válido y encriptado con la clave criptográfica correcta, etc. Entonces **desencriptaría el response** y lo procesaría.
-
+
El cliente (navegador) sabrá que el response proviene del servidor correcto porque está utilizando la criptografía que acordaron usando el **certificado HTTPS** anteriormente.
@@ -163,7 +163,7 @@ En el mismo servidor (o servidores), podrían haber **múltiples aplicaciones**,
Solo un proceso puede estar gestionando la IP y puerto específica (el TLS Termination Proxy en nuestro ejemplo) pero las otras aplicaciones/procesos pueden estar ejecutándose en el/los servidor(es) también, siempre y cuando no intenten usar la misma **combinación de IP pública y puerto**.
-
+
De esa manera, el TLS Termination Proxy podría gestionar HTTPS y certificados para **múltiples dominios**, para múltiples aplicaciones, y luego transmitir los requests a la aplicación correcta en cada caso.
@@ -173,7 +173,7 @@ En algún momento en el futuro, cada certificado **expiraría** (alrededor de 3
Y entonces, habría otro programa (en algunos casos es otro programa, en algunos casos podría ser el mismo TLS Termination Proxy) que hablaría con Let's Encrypt y renovaría el/los certificado(s).
-
+
Los **certificados TLS** están **asociados con un nombre de dominio**, no con una dirección IP.
diff --git a/docs/es/docs/how-to/custom-docs-ui-assets.md b/docs/es/docs/how-to/custom-docs-ui-assets.md
index 444cf167e..0a03ff330 100644
--- a/docs/es/docs/how-to/custom-docs-ui-assets.md
+++ b/docs/es/docs/how-to/custom-docs-ui-assets.md
@@ -98,7 +98,7 @@ Probablemente puedas hacer clic derecho en cada enlace y seleccionar una opción
Y **ReDoc** utiliza el archivo:
-* `redoc.standalone.js`
+* `redoc.standalone.js`
Después de eso, tu estructura de archivos podría verse así:
@@ -129,14 +129,8 @@ Deberías ver un archivo JavaScript muy largo de **ReDoc**.
Podría comenzar con algo como:
```JavaScript
-/*!
- * ReDoc - OpenAPI/Swagger-generated API Reference Documentation
- * -------------------------------------------------------------
- * Version: "2.0.0-rc.18"
- * Repo: https://github.com/Redocly/redoc
- */
-!function(e,t){"object"==typeof exports&&"object"==typeof m
-
+/*! For license information please see redoc.standalone.js.LICENSE.txt */
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")):
...
```
diff --git a/docs/es/docs/tutorial/bigger-applications.md b/docs/es/docs/tutorial/bigger-applications.md
index 78165ef05..c3d8f0686 100644
--- a/docs/es/docs/tutorial/bigger-applications.md
+++ b/docs/es/docs/tutorial/bigger-applications.md
@@ -52,7 +52,7 @@ from app.routers import items
* También hay un subdirectorio `app/internal/` con otro archivo `__init__.py`, por lo que es otro "subpaquete de Python": `app.internal`.
* Y el archivo `app/internal/admin.py` es otro submódulo: `app.internal.admin`.
-
+
La misma estructura de archivos con comentarios:
@@ -270,7 +270,7 @@ Pero ese archivo no existe, nuestras dependencias están en un archivo en `app/d
Recuerda cómo se ve nuestra estructura de aplicación/archivo:
-
+
---
diff --git a/docs/ja/docs/deployment/concepts.md b/docs/ja/docs/deployment/concepts.md
index c6b21fd1b..a0d4fb35b 100644
--- a/docs/ja/docs/deployment/concepts.md
+++ b/docs/ja/docs/deployment/concepts.md
@@ -219,7 +219,7 @@ FastAPI アプリケーションでは、Uvicorn のようなサーバープロ
これらのワーカー・プロセスは、アプリケーションを実行するものであり、**リクエスト**を受けて**レスポンス**を返すための主要な計算を行い、あなたが変数に入れたものは何でもRAMにロードします。
-
+
そしてもちろん、同じマシンでは、あなたのアプリケーションとは別に、**他のプロセス**も実行されているでしょう。
diff --git a/docs/ja/docs/deployment/https.md b/docs/ja/docs/deployment/https.md
index ac40b0982..7b0f567aa 100644
--- a/docs/ja/docs/deployment/https.md
+++ b/docs/ja/docs/deployment/https.md
@@ -92,7 +92,7 @@ DNSサーバーでは、**取得したドメイン**をあなたのサーバー
DNSサーバーは、ブラウザに特定の**IPアドレス**を使用するように指示します。このIPアドレスは、DNSサーバーで設定した、あなたのサーバーが使用するパブリックIPアドレスになります。
-
+
### TLS Handshake の開始
@@ -100,7 +100,7 @@ DNSサーバーは、ブラウザに特定の**IPアドレス**を使用する
通信の最初の部分は、クライアントとサーバー間の接続を確立し、使用する暗号鍵などを決めるだけです。
-
+
TLS接続を確立するためのクライアントとサーバー間のこのやりとりは、**TLSハンドシェイク**と呼ばれます。
@@ -120,7 +120,7 @@ TLS Termination Proxyは、1つ以上の**TLS証明書**(HTTPS証明書)に
今回は、`someapp.example.com`の証明書を使うことになります。
-
+
クライアントは、そのTLS証明書を生成したエンティティ(この場合はLet's Encryptですが、これについては後述します)をすでに**信頼**しているため、その証明書が有効であることを**検証**することができます。
@@ -142,19 +142,19 @@ TLS Termination Proxyは、1つ以上の**TLS証明書**(HTTPS証明書)に
そこで、クライアントは**HTTPSリクエスト**を送信します。これは、暗号化されたTLSコネクションを介した単なるHTTPリクエストです。
-
+
### リクエストの復号化
TLS Termination Proxy は、合意が取れている暗号化を使用して、**リクエストを復号化**し、**プレーン (復号化された) HTTP リクエスト** をアプリケーションを実行しているプロセス (例えば、FastAPI アプリケーションを実行している Uvicorn を持つプロセス) に送信します。
-
+
### HTTP レスポンス
アプリケーションはリクエストを処理し、**プレーン(暗号化されていない)HTTPレスポンス** をTLS Termination Proxyに送信します。
-
+
### HTTPS レスポンス
@@ -162,7 +162,7 @@ TLS Termination Proxyは次に、事前に合意が取れている暗号(`someap
その後ブラウザでは、レスポンスが有効で正しい暗号キーで暗号化されていることなどを検証します。そして、ブラウザはレスポンスを**復号化**して処理します。
-
+
クライアント(ブラウザ)は、レスポンスが正しいサーバーから来たことを知ることができます。 なぜなら、そのサーバーは、以前に**HTTPS証明書**を使って合意した暗号を使っているからです。
@@ -172,7 +172,7 @@ TLS Termination Proxyは次に、事前に合意が取れている暗号(`someap
特定のIPとポート(この例ではTLS Termination Proxy)を扱うことができるのは1つのプロセスだけですが、他のアプリケーション/プロセスも、同じ**パブリックIPとポート**の組み合わせを使用しようとしない限り、サーバー上で実行することができます。
-
+
そうすれば、TLS Termination Proxy は、**複数のドメイン**や複数のアプリケーションのHTTPSと証明書を処理し、それぞれのケースで適切なアプリケーションにリクエストを送信することができます。
@@ -182,7 +182,7 @@ TLS Termination Proxyは次に、事前に合意が取れている暗号(`someap
その後、Let's Encryptと通信する別のプログラム(別のプログラムである場合もあれば、同じTLS Termination Proxyである場合もある)によって、証明書を更新します。
-
+
**TLS証明書**は、IPアドレスではなく、**ドメイン名に関連付けられて**います。
diff --git a/docs/ja/docs/virtual-environments.md b/docs/ja/docs/virtual-environments.md
new file mode 100644
index 000000000..791cf64a8
--- /dev/null
+++ b/docs/ja/docs/virtual-environments.md
@@ -0,0 +1,831 @@
+# 仮想環境
+
+Pythonプロジェクトの作業では、**仮想環境**(または類似の仕組み)を使用し、プロジェクトごとにインストールするパッケージを分離するべきでしょう。
+
+/// info | 情報
+
+もし、仮想環境の概要や作成方法、使用方法について既にご存知なら、このセクションをスキップすることができます。🤓
+
+///
+
+/// tip | 豆知識
+
+**仮想環境**は、**環境変数**とは異なります。
+
+**環境変数**は、プログラムが使用できるシステム内の変数です。
+
+**仮想環境**は、ファイルをまとめたディレクトリのことです。
+
+///
+
+/// info | 情報
+このページでは、**仮想環境**の使用方法と、そのはたらきについて説明します。
+
+もし**すべてを管理するツール**(Pythonのインストールも含む)を導入する準備ができているなら、uv をお試しください。
+
+///
+
+## プロジェクトの作成
+
+まず、プロジェクト用のディレクトリを作成します。
+
+私は通常 home/user ディレクトリの中に `code` というディレクトリを用意していて、プロジェクトごとに1つのディレクトリをその中に作成しています。
+
+
+
+```console
+// Go to the home directory
+$ cd
+// Create a directory for all your code projects
+$ mkdir code
+// Enter into that code directory
+$ cd code
+// Create a directory for this project
+$ mkdir awesome-project
+// Enter into that project directory
+$ cd awesome-project
+```
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+
+// You don't need to be in the old directory to deactivate, you can do it wherever you are, even after going to the other project 😎
+$ deactivate
+
+// Activate the virtual environment in prisoner-of-azkaban/.venv 🚀
+$ source .venv/bin/activate
+
+// Now when you run python, it will find the package sirius installed in this virtual environment ✨
+$ python main.py
+
+I solemnly swear 🐺
+```
+
+
+
+## 代替手段
+
+これは、あらゆる仕組みを**根本から**学ぶためのシンプルな入門ガイドです。
+
+仮想環境、パッケージの依存関係(requirements)、プロジェクトの管理には、多くの**代替手段**があります。
+
+準備が整い、パッケージの依存関係、仮想環境など**プロジェクト全体の管理**ツールを使いたいと考えたら、uv を試してみることをおすすめします。
+
+`uv` では以下のような多くのことができます:
+
+* 異なるバージョンも含めた**Python のインストール**
+* プロジェクトごとの**仮想環境**の管理
+* **パッケージ**のインストール
+* プロジェクトのパッケージの**依存関係やバージョン**の管理
+* パッケージとそのバージョンの、依存関係を含めた**厳密な**組み合わせを保持し、これによって、本番環境で、開発環境と全く同じようにプロジェクトを実行できる(これは**locking**と呼ばれます)
+* その他のさまざまな機能
+
+## まとめ
+
+ここまで読みすべて理解したなら、世間の多くの開発者と比べて、仮想環境について**あなたはより多くのことを知っています**。🤓
+
+これらの詳細を知ることは、将来、複雑に見える何かのデバッグにきっと役立つでしょう。しかし、その頃には、あなたは**そのすべての動作を根本から**理解しているでしょう。😎
diff --git a/docs/ko/docs/advanced/events.md b/docs/ko/docs/advanced/events.md
index ae349e7be..5f8fe0f1e 100644
--- a/docs/ko/docs/advanced/events.md
+++ b/docs/ko/docs/advanced/events.md
@@ -1,53 +1,165 @@
-# 이벤트: startup과 shutdown
+# Lifespan 이벤트
-필요에 따라 응용 프로그램이 시작되기 전이나 종료될 때 실행되는 이벤트 핸들러(함수)를 정의할 수 있습니다.
+애플리케이션 **시작 전**에 실행되어야 하는 로직(코드)을 정의할 수 있습니다. 이는 이 코드가 **한 번**만 실행되며, **애플리케이션이 요청을 받기 시작하기 전**에 실행된다는 의미입니다.
-이 함수들은 `async def` 또는 평범하게 `def`으로 선언할 수 있습니다.
+마찬가지로, 애플리케이션이 **종료될 때** 실행되어야 하는 로직(코드)을 정의할 수 있습니다. 이 경우, 이 코드는 **한 번**만 실행되며, **여러 요청을 처리한 후**에 실행됩니다.
+
+이 코드가 애플리케이션이 **요청을 받기 시작하기 전에** 실행되고, 요청 처리가 끝난 후 **종료 직전에** 실행되기 때문에 전체 애플리케이션의 **수명(Lifespan)**을 다룹니다. (잠시 후 "수명"이라는 단어가 중요해집니다 😉)
+
+이 방법은 전체 애플리케이션에서 사용해야 하는 **자원**을 설정하거나 요청 간에 **공유되는** 자원을 설정하고, 또는 그 후에 **정리**하는 데 매우 유용할 수 있습니다. 예를 들어, 데이터베이스 연결 풀 또는 공유되는 머신러닝 모델을 로드하는 경우입니다.
+
+
+## 사용 사례
+
+먼저 **사용 사례**를 예로 들어보고, 이를 어떻게 해결할 수 있는지 살펴보겠습니다.
+
+우리가 요청을 처리하기 위해 사용하고 싶은 **머신러닝 모델**이 있다고 상상해 봅시다. 🤖
+
+이 모델들은 요청 간에 공유되므로, 요청마다 모델이 하나씩 있는 것이 아니라, 여러 요청에서 동일한 모델을 사용합니다.
+
+모델을 로드하는 데 **상당한 시간이 걸린다고 상상해 봅시다**, 왜냐하면 모델이 **디스크에서 많은 데이터를 읽어야** 하기 때문입니다. 따라서 모든 요청에 대해 모델을 매번 로드하고 싶지 않습니다.
+
+모듈/파일의 최상위에서 모델을 로드할 수도 있지만, 그러면 **모델을 로드하는데** 시간이 걸리기 때문에, 단순한 자동화된 테스트를 실행할 때도 모델이 로드될 때까지 기다려야 해서 **테스트 속도가 느려집니다**.
+
+이 문제를 해결하려고 하는 것입니다. 요청을 처리하기 전에 모델을 로드하되, 애플리케이션이 요청을 받기 시작하기 직전에만 로드하고, 코드가 로드되는 동안은 로드하지 않도록 하겠습니다.
+
+## Lifespan
+
+`FastAPI` 애플리케이션의 `lifespan` 매개변수와 "컨텍스트 매니저"를 사용하여 *시작*과 *종료* 로직을 정의할 수 있습니다. (컨텍스트 매니저가 무엇인지 잠시 후에 설명드리겠습니다.)
+
+예제를 통해 시작하고, 그 후에 자세히 살펴보겠습니다.
+
+우리는 `yield`를 사용하여 비동기 함수 `lifespan()`을 다음과 같이 생성합니다:
+
+{* ../../docs_src/events/tutorial003.py hl[16,19] *}
+
+여기서 우리는 모델을 로드하는 비싼 *시작* 작업을 시뮬레이션하고 있습니다. `yield` 앞에서 (가짜) 모델 함수를 머신러닝 모델이 담긴 딕셔너리에 넣습니다. 이 코드는 **애플리케이션이 요청을 받기 시작하기 전**, *시작* 동안에 실행됩니다.
+
+그리고 `yield` 직후에는 모델을 언로드합니다. 이 코드는 **애플리케이션이 요청 처리 완료 후**, *종료* 직전에 실행됩니다. 예를 들어, 메모리나 GPU와 같은 자원을 해제하는 작업을 할 수 있습니다.
+
+/// tip | 팁
+
+`shutdown`은 애플리케이션을 **종료**할 때 발생합니다.
+
+새로운 버전을 시작해야 하거나, 그냥 실행을 멈추고 싶을 수도 있습니다. 🤷
+
+///
+
+### Lifespan 함수
+
+먼저 주목할 점은, `yield`를 사용하여 비동기 함수(async function)를 정의하고 있다는 것입니다. 이는 `yield`를 사용한 의존성과 매우 유사합니다.
+
+{* ../../docs_src/events/tutorial003.py hl[14:19] *}
+
+함수의 첫 번째 부분, 즉 `yield` 이전의 코드는 애플리케이션이 시작되기 **전에** 실행됩니다.
+
+그리고 `yield` 이후의 부분은 애플리케이션이 완료된 후 **나중에** 실행됩니다.
+
+### 비동기 컨텍스트 매니저
+
+함수를 확인해보면, `@asynccontextmanager`로 장식되어 있습니다.
+
+이것은 함수를 "**비동기 컨텍스트 매니저**"라고 불리는 것으로 변환시킵니다.
+
+{* ../../docs_src/events/tutorial003.py hl[1,13] *}
+
+파이썬에서 **컨텍스트 매니저**는 `with` 문에서 사용할 수 있는 것입니다. 예를 들어, `open()`은 컨텍스트 매니저로 사용할 수 있습니다:
+
+```Python
+with open("file.txt") as file:
+ file.read()
+```
+최근 버전의 파이썬에서는 **비동기 컨텍스트 매니저**도 있습니다. 이를 `async with`와 함께 사용합니다:
+
+```Python
+async with lifespan(app):
+ await do_stuff()
+```
+
+컨텍스트 매니저나 위와 같은 비동기 컨텍스트 매니저를 만들면, `with` 블록에 들어가기 전에 `yield` 이전의 코드가 실행되고, `with` 블록을 벗어난 후에는 `yield` 이후의 코드가 실행됩니다.
+
+위의 코드 예제에서는 직접 사용하지 않고, FastAPI에 전달하여 사용하도록 합니다.
+
+`FastAPI` 애플리케이션의 `lifespan` 매개변수는 **비동기 컨텍스트 매니저**를 받기 때문에, 새로운 `lifespan` 비동기 컨텍스트 매니저를 FastAPI에 전달할 수 있습니다.
+
+{* ../../docs_src/events/tutorial003.py hl[22] *}
+
+## 대체 이벤트 (사용 중단)
/// warning | 경고
-이벤트 핸들러는 주 응용 프로그램에서만 작동합니다. [하위 응용 프로그램 - 마운트](./sub-applications.md){.internal-link target=_blank}에서는 작동하지 않습니다.
+*시작*과 *종료*를 처리하는 권장 방법은 위에서 설명한 대로 `FastAPI` 애플리케이션의 `lifespan` 매개변수를 사용하는 것입니다. `lifespan` 매개변수를 제공하면 `startup`과 `shutdown` 이벤트 핸들러는 더 이상 호출되지 않습니다. `lifespan`을 사용할지, 모든 이벤트를 사용할지 선택해야 하며 둘 다 사용할 수는 없습니다.
+
+이 부분은 건너뛰셔도 좋습니다.
///
-## `startup` 이벤트
+*시작*과 *종료* 동안 실행될 이 로직을 정의하는 대체 방법이 있습니다.
+
+애플리케이션이 시작되기 전에 또는 종료될 때 실행해야 하는 이벤트 핸들러(함수)를 정의할 수 있습니다.
-응용 프로그램을 시작하기 전에 실행하려는 함수를 "startup" 이벤트로 선언합니다:
+이 함수들은 `async def` 또는 일반 `def`로 선언할 수 있습니다.
+
+### `startup` 이벤트
+
+애플리케이션이 시작되기 전에 실행되어야 하는 함수를 추가하려면, `"startup"` 이벤트로 선언합니다:
{* ../../docs_src/events/tutorial001.py hl[8] *}
-이 경우 `startup` 이벤트 핸들러 함수는 단순히 몇 가지 값으로 구성된 `dict` 형식의 "데이터베이스"를 초기화합니다.
+이 경우, `startup` 이벤트 핸들러 함수는 "database"라는 항목(단지 `dict`)을 일부 값으로 초기화합니다.
-하나 이상의 이벤트 핸들러 함수를 추가할 수도 있습니다.
+여러 개의 이벤트 핸들러 함수를 추가할 수 있습니다.
-그리고 응용 프로그램은 모든 `startup` 이벤트 핸들러가 완료될 때까지 요청을 받지 않습니다.
+애플리케이션은 모든 `startup` 이벤트 핸들러가 완료될 때까지 요청을 받기 시작하지 않습니다.
-## `shutdown` 이벤트
+### `shutdown` 이벤트
-응용 프로그램이 종료될 때 실행하려는 함수를 추가하려면 `"shutdown"` 이벤트로 선언합니다:
+애플리케이션이 종료될 때 실행되어야 하는 함수를 추가하려면, `"shutdown"` 이벤트로 선언합니다:
{* ../../docs_src/events/tutorial002.py hl[6] *}
-이 예제에서 `shutdown` 이벤트 핸들러 함수는 `"Application shutdown"`이라는 텍스트가 적힌 `log.txt` 파일을 추가할 것입니다.
+여기서, `shutdown` 이벤트 핸들러 함수는 `"Application shutdown"`이라는 텍스트를 `log.txt` 파일에 기록합니다.
/// info | 정보
-`open()` 함수에서 `mode="a"`는 "추가"를 의미합니다. 따라서 이미 존재하는 파일의 내용을 덮어쓰지 않고 새로운 줄을 추가합니다.
+`open()` 함수에서 `mode="a"`는 "추가"를 의미하므로, 파일에 있는 기존 내용은 덮어쓰지 않고 새로운 줄이 추가됩니다.
///
/// tip | 팁
-이 예제에서는 파일과 상호작용 하기 위해 파이썬 표준 함수인 `open()`을 사용하고 있습니다.
+이 경우, 우리는 표준 파이썬 `open()` 함수를 사용하여 파일과 상호작용하고 있습니다.
-따라서 디스크에 데이터를 쓰기 위해 "대기"가 필요한 I/O (입력/출력) 작업을 수행합니다.
+따라서 I/O(입출력) 작업이 포함되어 있어 디스크에 기록되는 것을 "기다리는" 과정이 필요합니다.
-그러나 `open()`은 `async`와 `await`을 사용하지 않기 때문에 이벤트 핸들러 함수는 `async def`가 아닌 표준 `def`로 선언하고 있습니다.
+하지만 `open()`은 `async`와 `await`를 사용하지 않습니다.
+
+그래서 우리는 이벤트 핸들러 함수를 `async def` 대신 일반 `def`로 선언합니다.
///
+### `startup`과 `shutdown`을 함께 사용
+
+*시작*과 *종료* 로직이 연결될 가능성이 높습니다. 예를 들어, 무언가를 시작한 후 끝내거나, 자원을 획득한 후 해제하는 등의 작업을 할 수 있습니다.
+
+이러한 작업을 별도의 함수로 처리하면 서로 로직이나 변수를 공유하지 않기 때문에 더 어려워집니다. 값들을 전역 변수에 저장하거나 비슷한 트릭을 사용해야 할 수 있습니다.
+
+그렇기 때문에 위에서 설명한 대로 `lifespan`을 사용하는 것이 권장됩니다.
+
+## 기술적 세부사항
+
+호기심 많은 분들을 위한 기술적인 세부사항입니다. 🤓
+
+ASGI 기술 사양에 따르면, 이는 Lifespan Protocol의 일부이며, `startup`과 `shutdown`이라는 이벤트를 정의합니다.
+
/// info | 정보
-이벤트 핸들러에 관한 내용은 Starlette 이벤트 문서에서 추가로 확인할 수 있습니다.
+Starlette의 `lifespan` 핸들러에 대해 더 읽고 싶다면 Starlette의 Lifespan 문서에서 확인할 수 있습니다.
+
+이 문서에는 코드의 다른 영역에서 사용할 수 있는 lifespan 상태를 처리하는 방법도 포함되어 있습니다.
///
+
+## 서브 애플리케이션
+
+🚨 이 lifespan 이벤트(`startup`과 `shutdown`)는 메인 애플리케이션에 대해서만 실행되며, [서브 애플리케이션 - Mounts](sub-applications.md){.internal-link target=_blank}에는 실행되지 않음을 유의하세요.
diff --git a/docs/ko/docs/tutorial/extra-models.md b/docs/ko/docs/tutorial/extra-models.md
new file mode 100644
index 000000000..8e4559061
--- /dev/null
+++ b/docs/ko/docs/tutorial/extra-models.md
@@ -0,0 +1,223 @@
+# 추가 모델
+
+지난 예제에 이어서, 연관된 모델을 여러개 갖는 것은 흔한 일입니다.
+
+특히 사용자 모델의 경우에 그러한데, 왜냐하면:
+
+* **입력 모델** 은 비밀번호를 가져야 합니다.
+* **출력 모델** 은 비밀번호를 가지면 안됩니다.
+* **데이터베이스 모델** 은 해시처리된 비밀번호를 가질 것입니다.
+
+/// danger | 위험
+
+절대 사용자의 비밀번호를 평문으로 저장하지 마세요. 항상 이후에 검증 가능한 "안전한 해시(secure hash)"로 저장하세요.
+
+만약 이게 무엇인지 모르겠다면, [security chapters](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}.에서 비밀번호 해시에 대해 배울 수 있습니다.
+
+///
+
+## 다중 모델
+
+아래는 비밀번호 필드와 해당 필드가 사용되는 위치를 포함하여, 각 모델들이 어떤 형태를 가질 수 있는지 전반적인 예시입니다:
+
+{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *}
+
+
+/// info | 정보
+
+Pydantic v1에서는 해당 메서드가 `.dict()`로 불렸으며, Pydantic v2에서는 `.model_dump()`로 이름이 변경되었습니다. `.dict()`는 여전히 지원되지만 더 이상 권장되지 않습니다.
+
+여기에서 사용하는 예제는 Pydantic v1과의 호환성을 위해 `.dict()`를 사용하지만, Pydantic v2를 사용할 수 있다면 `.model_dump()`를 사용하는 것이 좋습니다.
+
+///
+
+### `**user_in.dict()` 에 대하여
+
+#### Pydantic의 `.dict()`
+
+`user_in`은 Pydantic 모델 클래스인 `UserIn`입니다.
+
+Pydantic 모델은 모델 데이터를 포함한 `dict`를 반환하는 `.dict()` 메서드를 제공합니다.
+
+따라서, 다음과 같이 Pydantic 객체 `user_in`을 생성할 수 있습니다:
+
+```Python
+user_in = UserIn(username="john", password="secret", email="john.doe@example.com")
+```
+
+그 다음, 다음과 같이 호출합니다:
+
+```Python
+user_dict = user_in.dict()
+```
+
+이제 변수 `user_dict`에 데이터가 포함된 `dict`를 가지게 됩니다(이는 Pydantic 모델 객체가 아닌 `dict`입니다).
+
+그리고 다음과 같이 호출하면:
+
+```Python
+print(user_dict)
+```
+
+Python의 `dict`가 다음과 같이 출력됩니다:
+
+```Python
+{
+ 'username': 'john',
+ 'password': 'secret',
+ 'email': 'john.doe@example.com',
+ 'full_name': None,
+}
+```
+
+#### `dict` 언패킹(Unpacking)
+
+`user_dict`와 같은 `dict`를 함수(또는 클래스)에 `**user_dict`로 전달하면, Python은 이를 "언팩(unpack)"합니다. 이 과정에서 `user_dict`의 키와 값을 각각 키-값 인자로 직접 전달합니다.
+
+따라서, 위에서 생성한 `user_dict`를 사용하여 다음과 같이 작성하면:
+
+```Python
+UserInDB(**user_dict)
+```
+
+다음과 같은 결과를 생성합니다:
+
+```Python
+UserInDB(
+ username="john",
+ password="secret",
+ email="john.doe@example.com",
+ full_name=None,
+)
+```
+
+혹은 더 정확히 말하자면, `user_dict`를 직접 사용하는 것은, 나중에 어떤 값이 추가되더라도 아래와 동일한 효과를 냅니다:
+
+```Python
+UserInDB(
+ username = user_dict["username"],
+ password = user_dict["password"],
+ email = user_dict["email"],
+ full_name = user_dict["full_name"],
+)
+```
+
+#### 다른 모델 데이터로 새 Pydantic 모델 생성
+
+위의 예제에서 `user_in.dict()`로부터 `user_dict`를 생성한 것처럼, 아래 코드는:
+
+```Python
+user_dict = user_in.dict()
+UserInDB(**user_dict)
+```
+
+다음과 동일합니다:
+
+```Python
+UserInDB(**user_in.dict())
+```
+
+...왜냐하면 `user_in.dict()`는 `dict`이며, 이를 `**`로 Python이 "언팩(unpack)"하도록 하여 `UserInDB`에 전달하기 때문입니다.
+
+따라서, 다른 Pydantic 모델의 데이터를 사용하여 새로운 Pydantic 모델을 생성할 수 있습니다.
+
+#### `dict` 언패킹(Unpacking)과 추가 키워드
+
+그리고 다음과 같이 추가 키워드 인자 `hashed_password=hashed_password`를 추가하면:
+
+```Python
+UserInDB(**user_in.dict(), hashed_password=hashed_password)
+```
+
+다음과 같은 결과를 생성합니다:
+
+```Python
+UserInDB(
+ username = user_dict["username"],
+ password = user_dict["password"],
+ email = user_dict["email"],
+ full_name = user_dict["full_name"],
+ hashed_password = hashed_password,
+)
+```
+
+/// warning | 경고
+
+추가적으로 제공된 함수 `fake_password_hasher`와 `fake_save_user`는 데이터 흐름을 시연하기 위한 예제일 뿐이며, 실제 보안을 제공하지 않습니다.
+
+///
+
+## 중복 줄이기
+
+코드 중복을 줄이는 것은 **FastAPI**의 핵심 아이디어 중 하나입니다.
+
+코드 중복은 버그, 보안 문제, 코드 비동기화 문제(한 곳은 업데이트되었지만 다른 곳은 업데이트되지 않는 문제) 등의 가능성을 증가시킵니다.
+
+그리고 이 모델들은 많은 데이터를 공유하면서 속성 이름과 타입을 중복하고 있습니다.
+
+더 나은 방법이 있습니다.
+
+`UserBase` 모델을 선언하여 다른 모델들의 기본(base)으로 사용할 수 있습니다. 그런 다음 이 모델을 상속받아 속성과 타입 선언(유형 선언, 검증 등)을 상속하는 서브클래스를 만들 수 있습니다.
+
+모든 데이터 변환, 검증, 문서화 등은 정상적으로 작동할 것입니다.
+
+이렇게 하면 각 모델 간의 차이점만 선언할 수 있습니다(평문 `password`가 있는 경우, `hashed_password`만 있는 경우, 혹은 비밀번호가 없는 경우):
+
+{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *}
+
+## `Union` 또는 `anyOf`
+
+두 가지 이상의 타입을 포함하는 `Union`으로 응답을 선언할 수 있습니다. 이는 응답이 그 중 하나의 타입일 수 있음을 의미합니다.
+
+OpenAPI에서는 이를 `anyOf`로 정의합니다.
+
+이를 위해 표준 Python 타입 힌트인 `typing.Union`을 사용할 수 있습니다:
+
+/// note | 참고
+
+`Union`을 정의할때는 더 구체적인 타입을 먼저 포함하고, 덜 구체적인 타입을 그 뒤에 나열해야합니다. 아래 예제에서는 `Union[PlaneItem, CarItem]` 를 보면, 더 구체적인 `PlaneItem`이 `CarItem`보다 앞에 위치합니다.
+
+///
+
+{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *}
+
+
+### Python 3.10에서 `Union`
+
+위의 예제에서는 `response_model` 인자 값으로 `Union[PlaneItem, CarItem]`을 전달합니다.
+
+이 경우, 이를 **타입 어노테이션(type annotation)** 이 아닌 **인자 값(argument value)** 으로 전달하고 있기 때문에 Python 3.10에서도 `Union`을 사용해야 합니다.
+
+만약 타입 어노테이션에 사용한다면, 다음과 같이 수직 막대(|)를 사용할 수 있습니다:
+
+```Python
+some_variable: PlaneItem | CarItem
+```
+
+하지만 이를 `response_model=PlaneItem | CarItem`과 같이 할당하면 에러가 발생합니다. 이는 Python이 이를 타입 어노테이션으로 해석하지 않고, `PlaneItem`과 `CarItem` 사이의 **잘못된 연산(invalid operation)**을 시도하기 때문입니다
+
+## 모델 리스트
+
+마찬가지로, 객체 리스트 형태의 응답을 선언할 수도 있습니다.
+
+이를 위해 표준 Python의 `typing.List`를 사용하세요(또는 Python 3.9 이상에서는 단순히 `list`를 사용할 수 있습니다):
+
+{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *}
+
+
+## 임의의 `dict` 응답
+
+Pydantic 모델을 사용하지 않고, 키와 값의 타입만 선언하여 평범한 임의의 `dict`로 응답을 선언할 수도 있습니다.
+
+이는 Pydantic 모델에 필요한 유효한 필드/속성 이름을 사전에 알 수 없는 경우에 유용합니다.
+
+이 경우, `typing.Dict`를 사용할 수 있습니다(또는 Python 3.9 이상에서는 단순히 `dict`를 사용할 수 있습니다):
+
+{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *}
+
+
+## 요약
+
+여러 Pydantic 모델을 사용하고, 각 경우에 맞게 자유롭게 상속하세요.
+
+엔터티가 서로 다른 "상태"를 가져야 하는 경우, 엔터티당 단일 데이터 모델을 사용할 필요는 없습니다. 예를 들어, 사용자 "엔터티"가 `password`, `password_hash`, 또는 비밀번호가 없는 상태를 포함할 수 있는 경우처럼 말입니다.
diff --git a/docs/ko/docs/tutorial/security/oauth2-jwt.md b/docs/ko/docs/tutorial/security/oauth2-jwt.md
new file mode 100644
index 000000000..d8bac8346
--- /dev/null
+++ b/docs/ko/docs/tutorial/security/oauth2-jwt.md
@@ -0,0 +1,273 @@
+# 패스워드 해싱을 이용한 OAuth2, JWT 토큰을 사용하는 Bearer 인증
+
+모든 보안 흐름을 구성했으므로, 이제 JWT 토큰과 패스워드 해싱을 사용해 애플리케이션을 안전하게 만들 것입니다.
+
+이 코드는 실제로 애플리케이션에서 패스워드를 해싱하여 DB에 저장하는 등의 작업에 활용할 수 있습니다.
+
+이전 장에 이어서 시작해 봅시다.
+
+## JWT
+
+JWT 는 "JSON Web Tokens" 을 의미합니다.
+
+JSON 객체를 공백이 없는 긴 문자열로 인코딩하는 표준이며, 다음과 같은 형태입니다:
+
+```
+eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
+```
+
+JWT는 암호화되지 않아 누구든지 토큰에서 정보를 복원할 수 있습니다.
+
+하지만 JWT는 서명되어 있습니다. 그래서 자신이 발급한 토큰을 받았을 때, 실제로 자신이 발급한게 맞는지 검증할 수 있습니다.
+
+만료 기간이 일주일인 토큰을 발행했다고 가정해 봅시다. 다음 날 사용자가 토큰을 가져왔을 때, 그 사용자가 시스템에 여전히 로그인되어 있다는 것을 알 수 있습니다.
+
+일주일 뒤에는 토큰이 만료될 것이고, 사용자는 인가되지 않아 새 토큰을 받기 위해 다시 로그인해야 할 것입니다. 만약 사용자(또는 제3자)가 토큰을 수정하거나 만료일을 변경하면, 서명이 일치하지 않기 때문에 알아챌 수 있을 것입니다.
+
+만약 JWT 토큰을 다뤄보고, 작동 방식도 알아보고 싶다면 https://jwt.io 을 확인하십시오.
+
+## `PyJWT` 설치
+
+파이썬으로 JWT 토큰을 생성하고 검증하려면 `PyJWT` 를 설치해야 합니다.
+
+[가상환경](../../virtual-environments.md){.internal-link target=_blank} 을 만들고 활성화한 다음 `pyjwt` 를 설치하십시오:
+
+
+
+/// info | 참고
+
+RSA나 ECDSA 같은 전자 서명 알고리즘을 사용하려면, `pyjwt[crypto]`라는 암호화 라이브러리 의존성을 설치해야 합니다.
+
+더 자세한 내용은 PyJWT 설치 에서 확인할 수 있습니다.
+
+///
+
+## 패스워드 해싱
+
+"해싱(Hashing)"은 어떤 내용(여기서는 패스워드)을 해석할 수 없는 일련의 바이트 집합(단순 문자열)으로 변환하는 것을 의미합니다.
+
+동일한 내용(똑같은 패스워드)을 해싱하면 동일한 문자열을 얻습니다.
+
+하지만 그 문자열을 다시 패스워드로 되돌릴 수는 없습니다.
+
+### 패스워드를 해싱하는 이유
+
+데이터베이스를 탈취당하더라도, 침입자는 사용자의 평문 패스워드 대신 해시 값만 얻을 수 있습니다.
+
+따라서 침입자는 훔친 사용자 패스워드를 다른 시스템에서 활용할 수 없습니다. (대다수 사용자가 여러 시스템에서 동일한 패스워드를 사용하기 때문에 평문 패스워드가 유출되면 위험합니다.)
+
+## `passlib` 설치
+
+PassLib는 패스워드 해시를 다루는 훌륭한 파이썬 패키지입니다.
+
+많은 안전한 해시 알고리즘과 도구들을 지원합니다.
+
+추천하는 알고리즘은 "Bcrypt"입니다.
+
+[가상환경](../../virtual-environments.md){.internal-link target=_blank} 을 만들고 활성화한 다음 PassLib와 Bcrypt를 설치하십시오:
+
+
+
+/// tip | 팁
+
+`passlib`를 사용하여, **Django**, **Flask** 의 보안 플러그인이나 다른 도구로 생성한 패스워드를 읽을 수 있도록 설정할 수도 있습니다.
+
+예를 들자면, FastAPI 애플리케이션과 Django 애플리케이션이 같은 데이터베이스에서 데이터를 공유할 수 있습니다. 또는 같은 데이터베이스를 사용하여 Django 애플리케이션을 점진적으로 마이그레이션 할 수도 있습니다.
+
+그리고 사용자는 FastAPI 애플리케이션과 Django 애플리케이션에 동시에 로그인할 수 있습니다.
+
+///
+
+## 패스워드의 해시와 검증
+
+필요한 도구를 `passlib`에서 임포트합니다.
+
+PassLib "컨텍스트(context)"를 생성합니다. 이것은 패스워드를 해싱하고 검증하는데 사용합니다.
+
+/// tip | 팁
+
+PassLib 컨텍스트는 다양한 해싱 알고리즘을 사용할 수 있는 기능을 제공하며, 더 이상 사용이 권장되지 않는 오래된 해싱 알고리즘을 검증하는 기능도 포함되어 있습니다.
+
+예를 들어, 다른 시스템(Django 같은)에서 생성한 패스워드를 읽고 검증할 수 있으며, 새로운 패스워드를 Bcrypt 같은 다른 알고리즘으로 해싱할 수도 있습니다.
+
+그리고 동시에 그런 모든 알고리즘과 호환성을 유지합니다.
+
+///
+
+사용자로부터 받은 패스워드를 해싱하는 유틸리티 함수를 생성합니다.
+
+그리고 받은 패스워드가 저장된 해시와 일치하는지 검증하는 또 다른 유틸리티 함수도 생성합니다.
+
+그리고 사용자를 인증하고 반환하는 또 다른 함수도 생성합니다.
+
+{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *}
+
+/// note
+
+새로운 (가짜) 데이터베이스 `fake_users_db`를 확인하면, 해시 처리된 패스워드가 어떻게 생겼는지 볼 수 있습니다: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`.
+
+///
+
+## JWT 토큰 처리
+
+설치된 모듈을 임포트 합니다.
+
+JWT 토큰 서명에 사용될 임의의 비밀키를 생성합니다.
+
+안전한 임의의 비밀키를 생성하려면 다음 명령어를 사용하십시오:
+
+
+
+그리고 생성한 비밀키를 복사해 변수 `SECRET_KEY`에 대입합니다. (이 예제의 변수 값을 그대로 사용하지 마십시오.)
+
+JWT 토큰을 서명하는 데 사용될 알고리즘을 위한 변수 `ALGORITHM` 을 생성하고 `"HS256"` 으로 설정합니다.
+
+토큰 만료 기간을 위한 변수를 생성합니다.
+
+응답을 위한 토큰 엔드포인트에 사용될 Pydantic 모델을 정의합니다.
+
+새 액세스 토큰을 생성하기 위한 유틸리티 함수를 생성합니다.
+
+{* ../../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 "주체(subject)" `sub`에 대한 기술 세부 사항
+
+JWT 명세에 따르면 토큰의 주체를 포함하는 `sub`라는 키가 있습니다.
+
+사용 여부는 선택사항이지만, 사용자의 식별 정보를 저장할 수 있으므로 여기서는 이를 사용합니다.
+
+JWT는 사용자를 식별하고 사용자가 API를 직접 사용할 수 있도록 허용하는 것 외에도 다른 용도로 사용될 수도 있습니다.
+
+예를 들어 "자동차"나 "블로그 게시물"을 식별하는 데 사용할 수 있습니다.
+
+그리고 "자동차를 운전하다"나 "블로그 게시물을 수정하다"처럼 해당 엔터티에 대한 권한을 추가할 수 있습니다.
+
+그 후 이 JWT 토큰을 사용자(또는 봇)에게 제공하면, 그들은 계정을 따로 만들 필요 없이 API가 생성한 JWT 토큰만으로 작업(자동차 운전 또는 블로그 게시물 편집)을 수행할 수 있습니다.
+
+이러한 개념을 활용하면 JWT는 훨씬 더 복잡한 시나리오에도 사용할 수 있습니다.
+
+이 경우 여러 엔터티가 동일한 ID를 가질 수 있습니다. 예를 들어 foo라는 ID를 가진 사용자, 자동차, 블로그 게시물이 있을 수 있습니다.
+
+그래서 ID 충돌을 방지하기 위해, 사용자의 JWT 토큰을 생성할 때 접두사로 `sub` 키를 추가할 수 있습니다. 예를 들어 `username:` 을 붙이는 방식입니다. 이 예제에서는 `sub` 값이 `username:johndoe`이 될 수 있습니다.
+
+가장 중요한 점은 `sub` 키는 전체 애플리케이션에서 고유한 식별자가 되어야 하며 문자열이어야 한다는 점입니다.
+
+## 확인해봅시다
+
+서버를 실행하고 문서로 이동하십시오: http://127.0.0.1:8000/docs.
+
+다음과 같은 사용자 인터페이스를 볼 수 있습니다:
+
+
+
+이전과 같은 방법으로 애플리케이션에 인증하십시오.
+
+다음 인증 정보를 사용하십시오:
+
+Username: `johndoe`
+Password: `secret`
+
+/// check
+
+코드 어디에도 평문 패스워드 "`secret`" 이 없다는 점에 유의하십시오. 해시된 버전만 있습니다.
+
+///
+
+
+
+`/users/me/` 를 호출하면 다음과 같은 응답을 얻을 수 있습니다:
+
+```JSON
+{
+ "username": "johndoe",
+ "email": "johndoe@example.com",
+ "full_name": "John Doe",
+ "disabled": false
+}
+```
+
+
+
+개발자 도구를 열어보면 전송된 데이터에 토큰만 포함된 것을 확인할 수 있습니다. 패스워드는 사용자를 인증하고 액세스 토큰을 받기 위한 첫 번째 요청에만 전송되며, 이후에는 전송되지 않습니다:
+
+
+
+/// note
+
+`Bearer `로 시작하는 `Authorization` 헤더에 주목하십시오.
+
+///
+
+## `scopes` 의 고급 사용법
+
+OAuth2는 "스코프(scopes)" 라는 개념을 갖고 있습니다.
+
+이를 사용하여 JWT 토큰에 특정 권한 집합을 추가할 수 있습니다.
+
+그 후 이 토큰을 사용자에게 직접 제공하거나 제3자에게 제공하여, 특정 제한사항 하에있는 API와 통신하도록 할 수 있습니다.
+
+**FastAPI** 에서의 사용 방법과 통합 방식은 **심화 사용자 안내서** 에서 자세히 배울 수 있습니다.
+
+## 요약
+
+지금까지 살펴본 내용을 바탕으로, OAuth2와 JWT 같은 표준을 사용하여 안전한 **FastAPI** 애플리케이션을 만들 수 있습니다.
+
+거의 모든 프레임워크에서 보안 처리는 상당히 복잡한 주제입니다.
+
+이를 단순화하는 많은 패키지는 데이터 모델, 데이터베이스, 사용 가능한 기능들에 대해 여러 제약이 있습니다. 그리고 지나치게 단순화하는 일부 패키지들은 심각한 보안 결함을 가질 수도 있습니다.
+
+---
+
+**FastAPI** 는 어떤 데이터베이스, 데이터 모델, 도구도 강요하지 않습니다.
+
+프로젝트에 가장 적합한 것을 선택할 수 있는 유연성을 제공합니다.
+
+그리고 `passlib` 와 `PyJWT` 처럼 잘 관리되고 널리 사용되는 패키지들을 바로 사용할 수 있습니다. **FastAPI** 는 외부 패키지 통합을 위해 복잡한 메커니즘이 필요하지 않기 때문입니다.
+
+그러나 유연성, 견고성, 보안성을 해치지 않으면서 과정을 단순화할 수 있는 도구들을 제공합니다.
+
+그리고 OAuth2와 같은 표준 프로토콜을 비교적 간단한 방법으로 구현하고 사용할 수 있습니다.
+
+더 세분화된 권한 체계를 위해 OAuth2의 "스코프"를 사용하는 방법은 **심화 사용자 안내서**에서 더 자세히 배울 수 있습니다. OAuth2의 스코프는 제3자 애플리케이션이 사용자를 대신해 그들의 API와 상호작용하도록 권한을 부여하기 위해, Facebook, Google, GitHub, Microsoft, Twitter 등의 많은 대형 인증 제공업체들이 사용하는 메커니즘입니다.
diff --git a/docs/ko/docs/virtual-environments.md b/docs/ko/docs/virtual-environments.md
new file mode 100644
index 000000000..0d10c3200
--- /dev/null
+++ b/docs/ko/docs/virtual-environments.md
@@ -0,0 +1,846 @@
+# 가상 환경
+
+Python 프로젝트를 작업할 때는 **가상 환경** (또는 이와 유사한 도구)을 사용하는 것이 좋습니다. 각 프로젝트 마다 설치하는 패키지를 분리하여 관리할 수 있습니다.
+
+/// info | 정보
+
+이미 가상 환경에 대해 잘 알고 있다면, 이 섹션은 건너 뛰어도 괜찮습니다. 🤓
+
+///
+
+/// tip | 팁
+
+**가상 환경(Virtual Environment)** 은 **환경 변수(Environment Variable)** 와 다릅니다.
+
+**환경 변수**는 시스템에 존재하며, 프로그램이 사용할 수 있는 변수입니다.
+
+**가상 환경**은 몇몇 파일로 구성된 하나의 디렉터리입니다.
+
+///
+
+/// 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`: Python 표준 라이브러리에 포함된 `venv` 모듈을 실행합니다.
+* `.venv`: 가상 환경을 `.venv` 디렉터리에 생성합니다.
+
+///
+
+////
+
+//// tab | `uv`
+
+`uv`가 설치되어 있다면, uv를 통해 가상 환경을 생성할 수 있습니다.
+
+
+
+```console
+$ uv venv
+```
+
+
+
+/// tip | 팁
+
+`uv`는 기본적으로 `.venv` 디렉터리에 가상 환경을 생성합니다.
+
+별도로 디렉터리 이름을 추가 인자로 넘겨 주면 경로를 지정 할 수 있습니다.
+
+///
+
+////
+
+해당 명령어는 `.venv` 디렉터리에 새로운 가상 환경을 생성합니다.
+
+/// details | `.venv` 또는 다른 이름
+
+가상 환경을 다른 디렉터리에 생성할 수도 있지만, 관례적으로 `.venv` 디렉터리 이름을 사용합니다.
+
+///
+
+## 가상 환경 활성화
+
+이후 실행하는 Python 명령어와 패키지 설치가 가상 환경을 따르도록, 가상 환경을 활성화하세요.
+
+/// tip | 팁
+
+**터미널을 새로 열고** 프로젝트 작업을 시작할 때는, **항상 이 작업을** 해주세요.
+
+///
+
+//// tab | Linux, macOS
+
+
+
+////
+
+/// tip | 팁
+
+가상 환경에 새로운 패키지를 설치할 때마다, 해당 환경을 다시 활성화하세요.
+
+이렇게 하면 해당 패키지로 설치된 **터미널(CLI) 프로그램**을 사용할 때, 전역에 설치된 다른 버전이 아니라, 가상 환경 안에 설치된 정확한 버전을 사용합니다.
+
+///
+
+## 가상 환경이 활성화 여부 확인
+
+가상 환경이 활성화되었는지 확인합니다. (이전 명령어가 제대로 작동했는지 확인합니다).
+
+/// tip | 팁
+
+이 단계는 **선택 사항**이지만, 모든 것이 예상대로 작동하고 있는지, 그리고 의도한 가상 환경이 활성화 되었는 지 **확인**하는 좋은 방법입니다.
+
+///
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+
+
+`python` 위치가 프로젝트 내부(이 예시에서는 `awesome-project`)의 `.venv/bin/python` 경로로 표시된다면 성공입니다. 🎉
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+`python` 위치가 프로젝트 내부(이 예시에서는 `awesome-project`)의 `.venv\bin\python` 경로로 표시된다면 성공입니다. 🎉
+
+////
+
+## pip 업그레이드
+
+/// tip | 팁
+
+`uv`를 사용한다면, `pip` 대신 `uv`로 패키지를 설치하게 되므로 `pip`을 업그레이드할 필요가 없습니다. 😎
+
+///
+
+`pip`을 사용하여 패키지를 설치하는 경우 (Python 표준 라이브러리에 포함되어 있습니다), **최신 버전으로 업그레이드**하는 것이 좋습니다.
+
+패키지 설치 중 발생하는 다양하고 특이한 에러들은 `pip` 업그레이드로 쉽게 해결되는 경우가 많습니다.
+
+/// tip | 팁
+
+이 작업은 보통 가상 환경을 생성한 **직후 한 번만** 하면 됩니다.
+
+///
+
+가상 환경이 활성화된 상태인지 확인한 후(앞서 설명한 명령어 사용), 아래 명령어를 실행하세요:
+
+
+
+## `.gitignore` 추가하기
+
+**Git**을 사용하고 있다면 (사용하는 것이 좋습니다), `.gitignore` 파일을 추가해서 `.venv` 디렉터리 전체를 Git에서 제외하세요.
+
+/// tip | 팁
+
+`uv`를 사용해 가상 환경을 생성했다면, 이미 이 작업이 자동으로 처리되어 있으므로 이 단계는 건너뛰어도 됩니다. 😎
+
+///
+
+/// tip | 팁
+
+이 작업도 마찬가지로, 가상 환경을 생성한 **직후 한 번만** 하면 됩니다.
+
+///
+
+
+
+/// details | 명령어 상세 설명
+
+* `echo "*"`: 터미널에 `*` 텍스트를 "출력"합니다 (다음 설명에서 조금 바뀝니다)
+* `>`: 왼쪽 명령어의 출력 내용을 터미널에 출력하지 않고, 오른쪽에 지정된 파일로 **기록(write)** 하라는 의미입니다.
+* `.gitignore`: 출력된 텍스트가 기록될 파일 이름입니다.
+
+그리고 Git에서 `*`는 "모든 것"을 의미합니다. 따라서 `.venv` 디렉터리 안의 모든 것을 무시하게 됩니다.
+
+이 명령어는 다음과 같은 내용을 가진 `.gitignore` 파일을 생성합니다:
+
+
+```gitignore
+*
+```
+
+///
+
+## 패키지 설치
+
+가상 환경을 활성화한 후, 그 안에 필요한 패키지들을 설치할 수 있습니다.
+
+/// tip | 팁
+
+프로젝트에서 필요한 패키지를 설치하거나 업그레이드할 때는 이 작업을 **한 번만** 하면 됩니다.
+
+만약 특정 패키지의 버전을 업그레이드하거나, 새로운 패키지를 추가할 필요가 생기면 **다시 이 작업을 반복**하면 됩니다.
+
+///
+
+### 패키지 직접 설치
+
+급하게 작업하거나, 프로젝트에 필요한 패키지 목록을 따로 파일로 관리하고 싶지 않은 경우, 패키지를 직접 설치할 수도 있습니다.
+
+/// tip | 팁
+
+패키지 이름과 버전 정보를 파일에 정리해두는 것(예: `requirements.txt` 또는 `pyproject.toml`)은 (매우) 좋은 생각입니다.
+
+///
+
+//// tab | `pip`
+
+
+
+////
+
+/// details | `requirements.txt`
+
+다음은 몇 가지 패키지를 포함한 `requirements.txt`의 예시입니다:
+
+```requirements.txt
+fastapi[standard]==0.113.0
+pydantic==2.8.0
+```
+
+///
+
+## 프로그램 실행
+
+가상 환경을 활성화한 후에는 프로그램을 실행할 수 있습니다. 이때 해당 가상 환경에 설치된 Python과 패키지들이 사용됩니다.
+
+
+
+## 에디터 설정
+
+에디터를 사용할 경우, 앞서 만든 가상 환경을 사용하도록 설정하는 것이 좋습니다. (대부분의 에디터는 자동으로 감지하기도 합니다.)
+이렇게 하면 자동 완성 기능이나 코드 내 오류 표시 기능을 제대로 사용할 수 있습니다.
+
+예시:
+
+* VS Code
+* PyCharm
+
+/// tip | 팁
+
+이 설정은 보통 가상 환경을 **처음 만들었을 때 한 번만** 해주면 됩니다.
+
+///
+
+## 가상 환경 비활성화
+
+프로젝트 작업이 끝났다면, 가상 환경을 **비활성화**할 수 있습니다.
+
+
+
+```console
+$ deactivate
+```
+
+
+
+이렇게 하면 이후에 `python` 명령어를 실행했을 때, 가상 환경의 Python이나 그 안에 설치된 패키지들을 사용하지 않게 됩니다.
+
+## 이제 작업할 준비가 되었습니다
+
+이제 프로젝트 작업을 시작할 준비가 완료되었습니다.
+
+
+/// tip | 팁
+
+위 내용을 더 깊이 이해하고 싶으신가요?
+
+그렇다면 계속 읽어 주세요. 👇🤓
+
+///
+
+## 가상 환경을 왜 사용하는가
+
+FastAPI를 사용하려면 먼저 Python을 설치해야 합니다.
+
+그 후에는 FastAPI와 함께 사용할 **기타 패키지들**을 **설치**해야 합니다.
+
+패키지를 설치할 때 보통 Python에 기본 포함된 `pip` 명령어(또는 유사한 도구)를 사용합니다.
+
+하지만 `pip`을 그냥 직접 사용하면, 해당 패키지들은 **전역 Python 환경**(시스템 전체에 설치된 Python)에 설치됩니다.
+
+### 문제점
+
+그렇다면, 전역 Python 환경에 패키지를 설치하면 어떤 문제가 발생할까요?
+
+어느 시점이 되면, **서로 다른 패키지들**에 의존하는 여러 개의 프로그램을 작성하게 될 것입니다. 그리고 이들 중 일부는 **같은 패키지의 서로 다른 버전**을 필요로 할 수 있습니다. 😱
+
+예를 들어, `마법사의 돌(philosophers-stone)` 프로젝트를 만들었다고 가정해봅시다. 이 프로그램은 `해리 포터(harry)`라는 패키지의 `v1` 버전을 **의존**합니다. 따라서 `harry`를 설치해야 합니다.
+
+```mermaid
+flowchart LR
+ stone(philosophers-stone) -->|requires| harry-1[harry v1]
+```
+
+그런데 나중에 `아즈카반의 죄수(prisoner-of-azkaban)`이라는 또 다른 프로젝트를 만들게 되었고, 이 프로젝트도 역시 `harry` 패키지를 사용합니다. 그런데 이 프로젝트는 `harry`의 `v3` 버전이 필요합니다.
+
+```mermaid
+flowchart LR
+ azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3]
+```
+
+하지만 이제 문제가 생깁니다. 로컬 가상 환경 대신에 전역 환경에 패키지를 설치하게 되면, 어떤 버전의 `harry`를 설치할지를 선택해야 하기 때문입니다.
+
+예를 들어, `마법사의 돌(philosophers-stone)`을 실행하고 싶다면 먼저 `harry` `v1` 버전을 다음과 같이 설치 해야 합니다:
+
+
+
+```console
+$ pip install "harry==1"
+```
+
+
+
+그러면 결국 전역 Python 환경에는 `harry` `v1`버전이 설치된 상태가 됩니다.
+
+```mermaid
+flowchart LR
+ subgraph global[global env]
+ harry-1[harry v1]
+ end
+ subgraph stone-project[philosophers-stone project]
+ stone(philosophers-stone) -->|requires| harry-1
+ end
+```
+
+하지만 이제 `아즈카반의 죄수(prisoner-of-azkaban)`을 실행하고 싶다면, `harry` `v1`버전을 제거하고 `harry` `v3`버전을 설치해야 합니다. (또는 단순히 `v3`버전을 설치하는 것만으로도 기존의 `v1`버전이 자동으로 제거됩니다.)
+
+
+
+```console
+$ pip install "harry==3"
+```
+
+
+
+그렇게 하면 이제 전역 Python 환경에는 `harry` `v3`버전이 설치된 상태가 됩니다.
+
+그리고 다시 `마법사의 돌(philosophers-stone)`을 실행하려고 하면, **작동하지** 않을 수 있습니다. 왜냐하면 이 프로그램은 `harry` `v1`버전을 필요로 하기 때문입니다.
+
+```mermaid
+flowchart LR
+ subgraph global[global env]
+ harry-1[harry v1]
+ style harry-1 fill:#ccc,stroke-dasharray: 5 5
+ harry-3[harry v3]
+ end
+ subgraph stone-project[philosophers-stone project]
+ stone(philosophers-stone) -.-x|⛔️| harry-1
+ end
+ subgraph azkaban-project[prisoner-of-azkaban project]
+ azkaban(prisoner-of-azkaban) --> |requires| harry-3
+ end
+```
+
+/// tip | 팁
+
+Python 패키지들은 **새 버전**에서 **호환성 문제(breaking changes)**가 발생하지 않도록 최대한 노력하는 것이 일반적입니다. 하지만 그래도 안전하게 작업하려면, 테스트를 실행해보면서 새 버전을 의도적으로 설치하는 것이 좋습니다.
+
+///
+
+이제, 이런 일이 여러분의 **모든 프로젝트**가 사용하는 **수많은 패키지들**에서 동시에 발생한다고 상상해보세요. 이는 매우 관리하기 어려우며, 결국 **서로 호환되지 않는 버전**의 패키지로 프로젝트를 실행하게 될 가능성이 높고, 그로 인해 어떤 문제가 왜 발생하는지 알 수 없게 될 수 있습니다.
+
+또한 사용하는 운영체제(Linux, Windows, macOS 등)에 따라 Python이 **미리 설치되어 있을 수도** 있습니다. 이런 경우에는 운영체제의 동작에 필요한 특정 버전의 패키지들이 함께 설치되어 있을 수 있습니다. 이 상태에서 전역 Python 환경에 임의의 패키지를 설치하면, 운영체제에 포함된 프로그램 일부가 **깨질 위험**도 있습니다.
+
+## 패키지들은 어디에 설치되는가
+
+Python을 설치하면, 컴퓨터에 여러 디렉터리와 파일들이 생성됩니다.
+
+이 중 일부 디렉터리는 사용자가 설치한 패키지들을 보관하는 역할을 합니다.
+
+예를 들어, 아래 명령어를 실행하면:
+
+
+
+```console
+// 지금 실행하지 않아도 됩니다, 그냥 예제일 뿐이에요 🤓
+$ pip install "fastapi[standard]"
+---> 100%
+```
+
+
+
+해당 명령어는 FastAPI 코드를 포함한 압축 파일을 다운로드합니다. 이 파일은 보통 PyPI에서 받아옵니다.
+
+또한 FastAPI가 의존하는 다른 패키지들도 함께 **다운로드**됩니다.
+
+그리고 그 모든 파일들을 **압축 해제**한 뒤, 컴퓨터의 특정 디렉터리에 저장합니다.
+
+기본적으로 이 파일들은 Python이 설치된 디렉터리 안, 즉 **전역 환경**에 내의 디렉터리에 저장됩니다.
+
+## 가상 환경이란
+
+전역 환경에 모든 패키지를 설치하면서 발생하는 문제에 대한 해결책은, 작업하는 **각 프로젝트마다 가상 환경**을 사용하는 것입니다.
+
+가상 환경은 전역 환경과 매우 유사한 하나의 **디렉터리**이며, 그 안에 해당 프로젝트를 위한 패키지들을 설치할 수 있습니다.
+
+이렇게 하면 각 프로젝트는 자체적인 가상 환경(`.venv` 디렉터리)을 가지게 되며, 그 안에 해당 프로젝트 전용 패키지들을 보유하게 됩니다.
+
+
+```mermaid
+flowchart TB
+ subgraph stone-project[philosophers-stone project]
+ stone(philosophers-stone) --->|requires| harry-1
+ subgraph venv1[.venv]
+ harry-1[harry v1]
+ end
+ end
+ subgraph azkaban-project[prisoner-of-azkaban project]
+ azkaban(prisoner-of-azkaban) --->|requires| harry-3
+ subgraph venv2[.venv]
+ harry-3[harry v3]
+ end
+ end
+ stone-project ~~~ azkaban-project
+```
+
+## 가상 환경 활성화 의미
+
+가상 환경을 활성화한다는 것은, 예를 들어 다음과 같은 명령어를 실행하는 것을 의미합니다:
+
+//// tab | Linux, macOS
+
+
+
+////
+
+이 명령어는 이후에 실행될 명령어에서 사용될 [환경 변수](environment-variables.md){.internal-link target=_blank} 몇 개를 생성하거나 수정합니다.
+
+이 변수들 중 하나가 바로 `PATH` 변수입니다.
+
+/// tip | 팁
+
+`PATH` 환경 변수에 대해 더 알고 싶다면 [환경 변수 문서의 PATH 환경 변수 섹션](environment-variables.md#path-environment-variable){.internal-link target=_blank}을 참고하세요.
+
+///
+
+가상 환경을 활성화하면, 가상 환경의 경로인 `.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
+```
+
+그리고 해당 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
+```
+
+그리고 해당 Python을 사용하게 됩니다.
+
+////
+
+중요한 세부 사항 중 하나는, 가상 환경의 경로가 `PATH` 변수의 가장 **앞**에 추가된다는 점입니다. 시스템은 사용 가능한 다른 Python들보다 **먼저** 이 경로를 찾습니다. 그래서 터미널에서 `python`을 실행하면, 전역 환경의 Python이 아닌 **가상 환경에 있는** Python이 사용됩니다. (예: 전역 환경에 설치된 `python`이 있더라도 그보다 우선합니다.)
+
+가상 환경을 활성화하면 이 외에도 몇 가지 다른 것들이 변경되지만, 이는 그중에서도 가장 중요한 변화 중 하나입니다.
+
+## 가상 환경 확인하기
+
+가상 환경이 활성화 되었는지 확인하려면, 아래 명령어를 사용할 수 있습니다:
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/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
+```
+
+
+
+하지만 `마법사의 돌(philosophers-stone)`의 가상 환경을 비활성화한 다음, `아즈카반의 죄수(prisoner-of-azkaban)` 프로젝트의 가상 환경을 활성화하면, 이제 `python` 명령어는 `아즈카반의 죄수(prisoner-of-azkaban)` 가상 환경의 Python을 사용하게 됩니다.
+
+
+
+```console
+$ cd ~/code/prisoner-of-azkaban
+
+// 이전 디렉터리에 있을 필요 없이, 어디서든 가상 환경을 비활성화할 수 있습니다. 다른 프로젝트 디렉터리로 이동한 후에도 괜찮아요 😎
+$ deactivate
+
+// prisoner-of-azkaban/.venv 가상 환경을 활성화합니다 🚀
+$ source .venv/bin/activate
+
+// 이제 python을 실행하면, 이 가상 환경에 설치된 sirius 패키지를 찾게 됩니다 ✨
+$ python main.py
+
+못된 짓을 꾸미고 있음을 엄숙히 맹세합니다.🧙
+ImportError는 이제 없습니다. 🐺
+```
+
+
+
+## 대안들
+
+이 문서는 여러분이 Python 프로젝트를 시작하고, **그 내부에서** 어떻게 돌아가는지 알려주는 간단한 가이드입니다.
+
+가상 환경, 패키지 의존성(Requirements), 프로젝트를 관리하는 방법에는 이 외에도 다양한 **대안**들이 존재합니다.
+
+만약 준비가 되었다면, **프로젝트 전체**, 패키지 의존성, 가상 환경 등을 통합적으로 **관리**할 수 있는 도구를 써보는 것도 좋습니다. 그럴 때 추천하는 도구가 바로 uv입니다.
+
+`uv`는 다양한 기능을 지원합니다:
+
+* 다양한 버전의 **Python 설치**
+* 각 프로젝트 별 **가상 환경 관리**
+* **패키지 설치**
+* 프로젝트의 **의존성과 버전** 관리
+* 설치된 패키지들과 그 버전을 **정확히 고정(lock)**해서,개발 환경과 운영 환경이 완전히 동일하게 작동할 수 있도록 보장
+* 이 외에도 다양한 기능을 지원
+
+## 결론
+
+여기까지 모두 읽고 이해했다면, 이제 많은 개발자들보다 가상 환경을 **훨씬 더 깊이 있게 이해**하게 되셨습니다. 🤓
+
+이런 세부적인 내용을 알고 있으면, 언젠가 복잡해 보이는 문제를 디버깅할 때 분명히 큰 도움이 될 것입니다. 이제는 **이 모든 것들이 내부에서 어떻게 작동하는지** 알고 있기 때문입니다. 😎
diff --git a/docs/pt/docs/deployment/concepts.md b/docs/pt/docs/deployment/concepts.md
index 8cf70d0b4..014ca3797 100644
--- a/docs/pt/docs/deployment/concepts.md
+++ b/docs/pt/docs/deployment/concepts.md
@@ -216,7 +216,7 @@ Este Processo de Gerenciador provavelmente seria o que escutaria na **porta** no
Esses processos de trabalho seriam aqueles que executariam seu aplicativo, eles executariam os cálculos principais para receber uma **solicitação** e retornar uma **resposta**, e carregariam qualquer coisa que você colocasse em variáveis na RAM.
-
+
E, claro, a mesma máquina provavelmente teria **outros processos** em execução, além do seu aplicativo.
diff --git a/docs/pt/docs/deployment/https.md b/docs/pt/docs/deployment/https.md
index 9ad419934..904d04eaa 100644
--- a/docs/pt/docs/deployment/https.md
+++ b/docs/pt/docs/deployment/https.md
@@ -85,7 +85,7 @@ Primeiro, o navegador iria verificar com os **servidores DNS** qual o **IP do do
Os servidores DNS iriam informar o navegador para utilizar algum **endereço IP** específico. Esse seria o endereço IP público em uso no seu servidor, que você configurou nos servidores DNS.
-
+
### Início do Handshake TLS
@@ -93,7 +93,7 @@ O navegador então irá comunicar-se com esse endereço IP na **porta 443** (a p
A primeira parte dessa comunicação é apenas para estabelecer a conexão entre o cliente e o servidor e para decidir as chaves criptográficas a serem utilizadas, etc.
-
+
Esse interação entre o cliente e o servidor para estabelecer uma conexão TLS é chamada de **Handshake TLS**.
@@ -111,7 +111,7 @@ Utilizando a **extensão SNI** discutida acima, o Proxy de Terminação TLS iria
Nesse caso, ele usaria o certificado para `someapp.example.com`.
-
+
O cliente já **confia** na entidade que gerou o certificado TLS (nesse caso, o Let's Encrypt, mas veremos sobre isso mais tarde), então ele pode **verificar** que o certificado é válido.
@@ -133,19 +133,19 @@ Agora que o cliente e servidor (especialmente o navegador e o Proxy de Terminaç
Então, o cliente envia uma **solicitação HTTPS**. Que é apenas uma solicitação HTTP sobre uma conexão TLS encriptada.
-
+
### Desencriptando a Solicitação
O Proxy de Terminação TLS então usaria a encriptação combinada para **desencriptar a solicitação**, e transmitiria a **solicitação básica (desencriptada)** para o processo executando a aplicação (por exemplo, um processo com Uvicorn executando a aplicação FastAPI).
-
+
### Resposta HTTP
A aplicação processaria a solicitação e retornaria uma **resposta HTTP básica (não encriptada)** para o Proxy de Terminação TLS.
-
+
### Resposta HTTPS
@@ -153,7 +153,7 @@ O Proxy de Terminação TLS iria **encriptar a resposta** utilizando a criptogra
No próximo passo, o navegador verifica que a resposta é válida e encriptada com a chave criptográfica correta, etc. E depois **desencripta a resposta** e a processa.
-
+
O cliente (navegador) saberá que a resposta vem do servidor correto por que ela usa a criptografia que foi combinada entre eles usando o **certificado HTTPS** anterior.
@@ -163,7 +163,7 @@ Podem existir **múltiplas aplicações** em execução no mesmo servidor (ou se
Apenas um processo pode estar vinculado a um IP e porta (o Proxy de Terminação TLS, por exemplo), mas outras aplicações/processos também podem estar em execução no(s) servidor(es), desde que não tentem usar a mesma **combinação de IP público e porta**.
-
+
Dessa forma, o Proxy de Terminação TLS pode gerenciar o HTTPS e os certificados de **múltiplos domínios**, para múltiplas aplicações, e então transmitir as requisições para a aplicação correta em cada caso.
@@ -173,7 +173,7 @@ Em algum momento futuro, cada certificado irá **expirar** (aproximadamente 3 me
E então, haverá outro programa (em alguns casos pode ser o próprio Proxy de Terminação TLS) que irá interagir com o Let's Encrypt e renovar o(s) certificado(s).
-
+
Os **certificados TLS** são **associados com um nome de domínio**, e não a um endereço IP.
diff --git a/docs/pt/docs/how-to/custom-docs-ui-assets.md b/docs/pt/docs/how-to/custom-docs-ui-assets.md
index 3adc7529e..b7de6c8bd 100644
--- a/docs/pt/docs/how-to/custom-docs-ui-assets.md
+++ b/docs/pt/docs/how-to/custom-docs-ui-assets.md
@@ -98,7 +98,7 @@ Você provavelmente pode clicar com o botão direito em cada link e selecionar u
E o **ReDoc** usa os arquivos:
-* `redoc.standalone.js`
+* `redoc.standalone.js`
Depois disso, sua estrutura de arquivos deve se parecer com:
@@ -129,14 +129,8 @@ Você deverá ver um arquivo JavaScript muito longo para o **ReDoc**.
Esse arquivo pode começar com algo como:
```JavaScript
-/*!
- * ReDoc - OpenAPI/Swagger-generated API Reference Documentation
- * -------------------------------------------------------------
- * Version: "2.0.0-rc.18"
- * Repo: https://github.com/Redocly/redoc
- */
-!function(e,t){"object"==typeof exports&&"object"==typeof m
-
+/*! For license information please see redoc.standalone.js.LICENSE.txt */
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")):
...
```
diff --git a/docs/pt/docs/tutorial/bigger-applications.md b/docs/pt/docs/tutorial/bigger-applications.md
index a094005fd..b621f3c72 100644
--- a/docs/pt/docs/tutorial/bigger-applications.md
+++ b/docs/pt/docs/tutorial/bigger-applications.md
@@ -52,7 +52,7 @@ from app.routers import items
* Há também um subdiretório `app/internal/` com outro arquivo `__init__.py`, então ele é outro "subpacote Python":`app.internal`.
* E o arquivo `app/internal/admin.py` é outro submódulo: `app.internal.admin`.
-
+
A mesma estrutura de arquivos com comentários:
@@ -270,7 +270,7 @@ Mas esse arquivo não existe, nossas dependências estão em um arquivo em `app/
Lembre-se de como nossa estrutura app/file se parece:
-
+
---
diff --git a/docs/ru/docs/deployment/concepts.md b/docs/ru/docs/deployment/concepts.md
index 7cdc29526..acfa1f4fe 100644
--- a/docs/ru/docs/deployment/concepts.md
+++ b/docs/ru/docs/deployment/concepts.md
@@ -216,7 +216,7 @@
Каждый из этих процессов будет запускать ваше приложение для обработки полученного **запроса** и возвращения вычисленного **ответа** и они будут использовать оперативную память.
-
+
Безусловно, на этом же сервере будут работать и **другие процессы**, которые не относятся к вашему приложению.
diff --git a/docs/ru/docs/deployment/https.md b/docs/ru/docs/deployment/https.md
index 85c4cce60..d8877a9a1 100644
--- a/docs/ru/docs/deployment/https.md
+++ b/docs/ru/docs/deployment/https.md
@@ -92,7 +92,7 @@
DNS-сервера присылают браузеру определённый **IP-адрес**, тот самый публичный IP-адрес вашего сервера, который вы указали в ресурсной "записи А" при настройке.
-
+
### Рукопожатие TLS
@@ -100,7 +100,7 @@ DNS-сервера присылают браузеру определённый
Первым шагом будет установление соединения между клиентом (браузером) и сервером и выбор криптографического ключа (для шифрования).
-
+
Эта часть клиент-серверного взаимодействия устанавливает TLS-соединение и называется **TLS-рукопожатием**.
@@ -118,7 +118,7 @@ DNS-сервера присылают браузеру определённый
То есть будет выбран сертификат для домена `someapp.example.com`.
-
+
Клиент уже **доверяет** тому, кто выдал этот TLS-сертификат (в нашем случае - Let's Encrypt, но мы ещё обсудим это), потому может **проверить**, действителен ли полученный от сервера сертификат.
@@ -140,19 +140,19 @@ DNS-сервера присылают браузеру определённый
Так клиент отправляет **HTTPS-запрос**. То есть обычный HTTP-запрос, но через зашифрованное TLS-содинение.
-
+
### Расшифровка запроса
Прокси-сервер, используя согласованный с клиентом ключ, расшифрует полученный **зашифрованный запрос** и передаст **обычный (незашифрованный) HTTP-запрос** процессу, запускающему приложение (например, процессу Uvicorn запускающему приложение FastAPI).
-
+
### HTTP-ответ
Приложение обработает запрос и вернёт **обычный (незашифрованный) HTTP-ответ** прокси-серверу.
-
+
### HTTPS-ответ
@@ -160,7 +160,7 @@ DNS-сервера присылают браузеру определённый
Наконец, браузер проверит ответ, в том числе, что тот зашифрован с нужным ключом, **расшифрует его** и обработает.
-
+
Клиент (браузер) знает, что ответ пришёл от правильного сервера, так как использует методы шифрования, согласованные ими раннее через **HTTPS-сертификат**.
@@ -171,7 +171,7 @@ DNS-сервера присылают браузеру определённый
Напомню, что только один процесс (например, прокси-сервер) может прослушивать определённый порт определённого IP-адреса.
Но другие процессы и приложения тоже могут работать на этом же сервере (серверах), если они не пытаются использовать уже занятую **комбинацию IP-адреса и порта** (сокет).
-
+
Таким образом, сервер завершения TLS может обрабатывать HTTPS-запросы и использовать сертификаты для **множества доменов** или приложений и передавать запросы правильным адресатам (другим приложениям).
@@ -181,7 +181,7 @@ DNS-сервера присылают браузеру определённый
Когда это произойдёт, можно запустить другую программу, которая подключится к Let's Encrypt и обновит сертификат(ы). Существуют прокси-серверы, которые могут сделать это действие самостоятельно.
-
+
**TLS-сертификаты** не привязаны к IP-адресу, но **связаны с именем домена**.
diff --git a/docs/ru/docs/tutorial/bigger-applications.md b/docs/ru/docs/tutorial/bigger-applications.md
index 7c3dc288f..8b9080d39 100644
--- a/docs/ru/docs/tutorial/bigger-applications.md
+++ b/docs/ru/docs/tutorial/bigger-applications.md
@@ -52,7 +52,7 @@ from app.routers import items
* Подкаталог `app/internal/`, содержащий файл `__init__.py`, является ещё одним суб-пакетом: `app.internal`.
* А файл `app/internal/admin.py` является ещё одним суб-модулем: `app.internal.admin`.
-
+
Та же самая файловая структура приложения, но с комментариями:
@@ -269,7 +269,7 @@ from .dependencies import get_token_header
Вспомните, как выглядит файловая структура нашего приложения:
-
+
---
diff --git a/docs/ru/docs/tutorial/cookie-param-models.md b/docs/ru/docs/tutorial/cookie-param-models.md
new file mode 100644
index 000000000..3a57443bb
--- /dev/null
+++ b/docs/ru/docs/tutorial/cookie-param-models.md
@@ -0,0 +1,76 @@
+# Модели параметров cookie
+
+Если у вас есть группа **cookies**, которые связаны между собой, вы можете создать **Pydantic-модель** для их объявления. 🍪
+
+Это позволит вам **переиспользовать модель** в **разных местах**, а также объявить проверки и метаданные сразу для всех параметров. 😎
+
+/// note | Заметка
+
+Этот функционал доступен с версии `0.115.0`. 🤓
+
+///
+
+/// tip | Совет
+
+Такой же подход применяется для `Query`, `Cookie`, и `Header`. 😎
+
+///
+
+## Pydantic-модель для cookies
+
+Объявите параметры **cookie**, которые вам нужны, в **Pydantic-модели**, а затем объявите параметр как `Cookie`:
+
+{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *}
+
+**FastAPI** **извлечёт** данные для **каждого поля** из **cookies**, полученных в запросе, и выдаст вам объявленную Pydantic-модель.
+
+## Проверка сгенерированной документации
+
+Вы можете посмотреть объявленные cookies в графическом интерфейсе Документации по пути `/docs`:
+
+
+
+
+
+/// info | Дополнительная информация
+
+Имейте в виду, что, поскольку **браузеры обрабатывают cookies** особым образом и под капотом, они **не** позволят **JavaScript** легко получить доступ к ним.
+
+Если вы перейдёте к **графическому интерфейсу документации API** по пути `/docs`, то сможете увидеть **документацию** по cookies для ваших *операций путей*.
+
+Но даже если вы **заполните данные** и нажмёте "Execute", поскольку графический интерфейс Документации работает с **JavaScript**, cookies не будут отправлены, и вы увидите сообщение об **ошибке** как будто не указывали никаких значений.
+
+///
+
+## Запрет дополнительных cookies
+
+В некоторых случаях (не особо часто встречающихся) вам может понадобиться **ограничить** cookies, которые вы хотите получать.
+
+Теперь ваш API сам решает, принимать ли cookies. 🤪🍪
+
+Вы можете сконфигурировать Pydantic-модель так, чтобы запретить (`forbid`) любые дополнительные (`extra`) поля:
+
+{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *}
+
+Если клиент попробует отправить **дополнительные cookies**, то в ответ он получит **ошибку**.
+
+Бедные баннеры cookies, они всеми силами пытаются получить ваше согласие — и всё ради того, чтобы 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-модели** для объявления **cookies** в **FastAPI**. 😎
diff --git a/docs/ru/docs/tutorial/header-param-models.md b/docs/ru/docs/tutorial/header-param-models.md
new file mode 100644
index 000000000..4f54e3e15
--- /dev/null
+++ b/docs/ru/docs/tutorial/header-param-models.md
@@ -0,0 +1,72 @@
+# Модели Header-параметров
+
+Если у вас есть группа связанных **header-параметров**, то вы можете объединить их в одну **Pydantic-модель**.
+
+Это позволит вам **переиспользовать модель** в **разных местах**, а также задать валидацию и метаданные сразу для всех параметров. 😎
+
+/// note | Заметка
+
+Этот функционал доступен в FastAPI начиная с версии `0.115.0`. 🤓
+
+///
+
+## Header-параметры в виде Pydantic-модели
+
+Объявите нужные **header-параметры** в **Pydantic-модели** и затем аннотируйте параметр как `Header`:
+
+{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *}
+
+**FastAPI** **извлечёт** данные для **каждого поля** из **заголовков** запроса и выдаст заданную вами Pydantic-модель.
+
+## Проверьте документацию
+
+Вы можете посмотреть нужные header-параметры в графическом интерфейсе сгенерированной документации по пути `/docs`:
+
+
+
+
+
+## Как запретить дополнительные заголовки
+
+В некоторых случаях (не особо часто встречающихся) вам может понадобиться **ограничить** заголовки, которые вы хотите получать.
+
+Вы можете использовать возможности конфигурации Pydantic-модели для того, чтобы запретить (`forbid`) любые дополнительные (`extra`) поля:
+
+{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *}
+
+Если клиент попробует отправить **дополнительные заголовки**, то в ответ он получит **ошибку**.
+
+Например, если клиент попытается отправить заголовок `tool` со значением `plumbus`, то в ответ он получит ошибку, сообщающую ему, что header-параметр `tool` не разрешен:
+
+```json
+{
+ "detail": [
+ {
+ "type": "extra_forbidden",
+ "loc": ["header", "tool"],
+ "msg": "Extra inputs are not permitted",
+ "input": "plumbus",
+ }
+ ]
+}
+```
+
+## Как отключить автоматическое преобразование подчеркиваний
+
+Как и в случае с обычными заголовками, если у вас в именах параметров имеются символы подчеркивания, они **автоматически преобразовываются в дефис**.
+
+Например, если в коде есть header-параметр `save_data`, то ожидаемый HTTP-заголовок будет `save-data` и именно так он будет отображаться в документации.
+
+Если по каким-то причинам вам нужно отключить данное автоматическое преобразование, это можно сделать и для Pydantic-моделей для header-параметров.
+
+{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *}
+
+/// warning | Внимание
+
+Перед тем как устанавливать для параметра `convert_underscores` значение `False`, имейте в виду, что некоторые HTTP-прокси и серверы не разрешают использовать заголовки с символами подчеркивания.
+
+///
+
+## Резюме
+
+Вы можете использовать **Pydantic-модели** для объявления **header-параметров** в **FastAPI**. 😎
diff --git a/docs/ru/docs/tutorial/request-form-models.md b/docs/ru/docs/tutorial/request-form-models.md
new file mode 100644
index 000000000..1034ed27f
--- /dev/null
+++ b/docs/ru/docs/tutorial/request-form-models.md
@@ -0,0 +1,78 @@
+# Модели форм
+
+Вы можете использовать **Pydantic-модели** для объявления **полей форм** в FastAPI.
+
+/// info | Дополнительная информация
+
+Чтобы использовать формы, сначала установите `python-multipart`.
+
+Убедитесь, что вы создали и активировали [виртуальное окружение](../virtual-environments.md){.internal-link target=_blank}, а затем установите пакет, например:
+
+```console
+$ pip install python-multipart
+```
+
+///
+
+/// note | Заметка
+
+Этот функционал доступен с версии `0.113.0`. 🤓
+
+///
+
+## Pydantic-модель для формы
+
+Вам просто нужно объявить **Pydantic-модель** с полями, которые вы хотите получить как **поля формы**, а затем объявить параметр как `Form`:
+
+{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *}
+
+**FastAPI** **извлечёт** данные для **каждого поля** из **данных формы** в запросе и выдаст вам объявленную Pydantic-модель.
+
+## Проверка сгенерированной документации
+
+Вы можете посмотреть поля формы в графическом интерфейсе Документации по пути `/docs`:
+
+
+
+
+
+## Запрет дополнительных полей формы
+
+В некоторых случаях (не особо часто встречающихся) вам может понадобиться **ограничить** поля формы только теми, которые объявлены в Pydantic-модели. И **запретить** любые **дополнительные** поля.
+
+/// note | Заметка
+
+Этот функционал доступен с версии `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/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/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/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/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/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/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/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/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/zh/docs/deployment/concepts.md b/docs/zh/docs/deployment/concepts.md
index 7a0b6c3d2..f7208da7c 100644
--- a/docs/zh/docs/deployment/concepts.md
+++ b/docs/zh/docs/deployment/concepts.md
@@ -220,7 +220,7 @@
这些工作进程将是运行您的应用程序的进程,它们将执行主要计算以接收 **请求** 并返回 **响应**,并且它们将加载您放入 RAM 中的变量中的任何内容。
-
+
当然,除了您的应用程序之外,同一台机器可能还运行**其他进程**。
diff --git a/docs/zh/docs/deployment/https.md b/docs/zh/docs/deployment/https.md
index 9c963d587..d994c4add 100644
--- a/docs/zh/docs/deployment/https.md
+++ b/docs/zh/docs/deployment/https.md
@@ -86,7 +86,7 @@
DNS 服务器会告诉浏览器使用某个特定的 **IP 地址**。 这将是你在 DNS 服务器中为你的服务器配置的公共 IP 地址。
-
+
### TLS 握手开始
@@ -94,7 +94,7 @@ DNS 服务器会告诉浏览器使用某个特定的 **IP 地址**。 这将是
通信的第一部分只是建立客户端和服务器之间的连接并决定它们将使用的加密密钥等。
-
+
客户端和服务器之间建立 TLS 连接的过程称为 **TLS 握手**。
@@ -112,7 +112,7 @@ TLS 终止代理可以访问一个或多个 **TLS 证书**(HTTPS 证书)。
在这种情况下,它将使用`someapp.example.com`的证书。
-
+
客户端已经**信任**生成该 TLS 证书的实体(在本例中为 Let's Encrypt,但我们稍后会看到),因此它可以**验证**该证书是否有效。
@@ -134,19 +134,19 @@ TLS 终止代理可以访问一个或多个 **TLS 证书**(HTTPS 证书)。
接下来,客户端发送一个 **HTTPS 请求**。 这其实只是一个通过 TLS 加密连接的 HTTP 请求。
-
+
### 解密请求
TLS 终止代理将使用协商好的加密算法**解密请求**,并将**(解密的)HTTP 请求**传输到运行应用程序的进程(例如运行 FastAPI 应用的 Uvicorn 进程)。
-
+
### HTTP 响应
应用程序将处理请求并向 TLS 终止代理发送**(未加密)HTTP 响应**。
-
+
### HTTPS 响应
@@ -154,7 +154,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**(
接下来,浏览器将验证响应是否有效和是否使用了正确的加密密钥等。然后它会**解密响应**并处理它。
-
+
客户端(浏览器)将知道响应来自正确的服务器,因为它使用了他们之前使用 **HTTPS 证书** 协商出的加密算法。
@@ -164,7 +164,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**(
只有一个进程可以处理特定的 IP 和端口(在我们的示例中为 TLS 终止代理),但其他应用程序/进程也可以在服务器上运行,只要它们不尝试使用相同的 **公共 IP 和端口的组合**。
-
+
这样,TLS 终止代理就可以为多个应用程序处理**多个域名**的 HTTPS 和证书,然后在每种情况下将请求传输到正确的应用程序。
@@ -174,7 +174,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**(
然后,会有另一个程序(在某些情况下是另一个程序,在某些情况下可能是同一个 TLS 终止代理)与 Let's Encrypt 通信并更新证书。
-
+
**TLS 证书** **与域名相关联**,而不是与 IP 地址相关联。
diff --git a/docs/zh/docs/deployment/manually.md b/docs/zh/docs/deployment/manually.md
index 30ee7a1e9..3dc5942e3 100644
--- a/docs/zh/docs/deployment/manually.md
+++ b/docs/zh/docs/deployment/manually.md
@@ -1,159 +1,157 @@
-# 手动运行服务器 - Uvicorn
+# 手动运行服务器
-在远程服务器计算机上运行 **FastAPI** 应用程序所需的主要东西是 ASGI 服务器程序,例如 **Uvicorn**。
+## 使用 `fastapi run` 命令
-有 3 个主要可选方案:
+简而言之,使用 `fastapi run` 来运行您的 FastAPI 应用程序:
-* Uvicorn:高性能 ASGI 服务器。
-* Hypercorn:与 HTTP/2 和 Trio 等兼容的 ASGI 服务器。
-* Daphne:为 Django Channels 构建的 ASGI 服务器。
-
-## 服务器主机和服务器程序
-
-关于名称,有一个小细节需要记住。 💡
-
-“**服务器**”一词通常用于指远程/云计算机(物理机或虚拟机)以及在该计算机上运行的程序(例如 Uvicorn)。
+
-请记住,当您一般读到“服务器”这个名词时,它可能指的是这两者之一。
+```console
+$ fastapi run main.py
-当提到远程主机时,通常将其称为**服务器**,但也称为**机器**(machine)、**VM**(虚拟机)、**节点**。 这些都是指某种类型的远程计算机,通常运行 Linux,您可以在其中运行程序。
+ FastAPI Starting production server 🚀
+ Searching for package file structure from directories
+ with __init__.py files
+ Importing from /home/user/code/awesomeapp
-## 安装服务器程序
+ module 🐍 main.py
-您可以使用以下命令安装 ASGI 兼容服务器:
+ code Importing the FastAPI app object from the module with
+ the following code:
-//// tab | Uvicorn
+ from main import app
-* Uvicorn,一个快如闪电 ASGI 服务器,基于 uvloop 和 httptools 构建。
+ 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
-```console
-$ pip install "uvicorn[standard]"
+ Logs:
----> 100%
+ 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 run --workers 4 main.py
-这将安装带有`standard`扩展包(以获得高性能)的 Uvicorn 和 Gunicorn。
+ FastAPI Starting production server 🚀
-## Run Gunicorn with Uvicorn Workers
+ Searching for package file structure from directories with
+ __init__.py files
+ Importing from /home/user/code/awesomeapp
-接下来你可以通过以下命令运行Gunicorn:
-
-
-
-```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.
-```
-
-
+ module 🐍 main.py
+ code Importing the FastAPI app object from the module with the
+ following code:
-让我们看看每个选项的含义:
+ from main import app
-* `main:app`:这与 Uvicorn 使用的语法相同,`main` 表示名为"`main`"的 Python 模块,因此是文件 `main.py`。 `app` 是 **FastAPI** 应用程序的变量名称。
- * 你可以想象 `main:app` 相当于一个 Python `import` 语句,例如:
+ app Using import string: main:app
- ```Python
- from main import app
- ```
+ server Server started at http://0.0.0.0:8000
+ server Documentation at http://0.0.0.0:8000/docs
- * 因此,`main:app` 中的冒号相当于 `from main import app` 中的 Python `import` 部分。
+ Logs:
-* `--workers`:要使用的worker进程数量,每个进程将运行一个 Uvicorn worker进程,在本例中为 4 个worker进程。
-
-* `--worker-class`:在worker进程中使用的与 Gunicorn 兼容的工作类。
- * 这里我们传递了 Gunicorn 可以导入和使用的类:
-
- ```Python
- import uvicorn.workers.UvicornWorker
- ```
-
-* `--bind`:这告诉 Gunicorn 要监听的 IP 和端口,使用冒号 (`:`) 分隔 IP 和端口。
- * 如果您直接运行 Uvicorn,则可以使用`--host 0.0.0.0`和`--port 80`,而不是`--bind 0.0.0.0:80`(Gunicorn 选项)。
-
-
-在输出中,您可以看到它显示了每个进程的 **PID**(进程 ID)(它只是一个数字)。
-
-你可以看到:
-
-* Gunicorn **进程管理器** 以 PID `19499` 开头(在您的情况下,它将是一个不同的数字)。
-* 然后它开始`Listening at: http://0.0.0.0:80`。
-* 然后它检测到它必须使用 `uvicorn.workers.UvicornWorker` 处的worker类。
-* 然后它启动**4个worker**,每个都有自己的PID:`19511`、`19513`、`19514`和`19515`。
-
-Gunicorn 还将负责管理**死进程**和**重新启动**新进程(如果需要保持worker数量)。 因此,这在一定程度上有助于上面列表中**重启**的概念。
-
-尽管如此,您可能还希望有一些外部的东西,以确保在必要时**重新启动 Gunicorn**,并且**在启动时运行它**等。
+ 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.
+```
-## Uvicorn with Workers
+
```console
-$ uvicorn main:app --reload
+$ fastapi dev main.py
-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 Starting development server 🚀
-
+ Searching for package file structure from directories
+ with __init__.py files
+ Importing from /home/user/code/awesomeapp
-/// note
+ module 🐍 main.py
-`uvicorn main:app` 命令含义如下:
+ code Importing the FastAPI app object from the module with
+ the following code:
-* `main`:`main.py` 文件(一个 Python「模块」)。
-* `app`:在 `main.py` 文件中通过 `app = FastAPI()` 创建的对象。
-* `--reload`:让服务器在更新代码后重新启动。仅在开发时使用该选项。
+ 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.
+```
+
+
在输出中,会有一行信息像下面这样:
@@ -38,7 +54,6 @@ $ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
-
该行显示了你的应用在本机所提供服务的 URL 地址。
### 查看
@@ -63,7 +78,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
前往 http://127.0.0.1:8000/redoc。
-你将会看到可选的自动生成文档 (由 ReDoc 提供):
+你将会看到可选的自动生成文档 (由 ReDoc 提供):

@@ -77,9 +92,9 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
#### API「模式」
-在这种场景下,OpenAPI 是一种规定如何定义 API 模式的规范。
+在这种场景下,OpenAPI 是一种规定如何定义 API 模式的规范。
-定义的 OpenAPI 模式将包括你的 API 路径,以及它们可能使用的参数等等。
+「模式」的定义包括你的 API 路径,以及它们可能使用的参数等等。
#### 数据「模式」
@@ -93,7 +108,7 @@ OpenAPI 为你的 API 定义 API 模式。该模式中包含了你的 API 发送
#### 查看 `openapi.json`
-如果你对原始的 OpenAPI 模式长什么样子感到好奇,其实它只是一个自动生成的包含了所有 API 描述的 JSON。
+如果你对原始的 OpenAPI 模式长什么样子感到好奇,FastAPI 自动生成了包含所有 API 描述的 JSON(模式)。
你可以直接在:http://127.0.0.1:8000/openapi.json 看到它。
@@ -101,7 +116,7 @@ OpenAPI 为你的 API 定义 API 模式。该模式中包含了你的 API 发送
```JSON
{
- "openapi": "3.0.2",
+ "openapi": "3.1.0",
"info": {
"title": "FastAPI",
"version": "0.1.0"
@@ -140,7 +155,7 @@ OpenAPI 为你的 API 定义 API 模式。该模式中包含了你的 API 发送
`FastAPI` 是直接从 `Starlette` 继承的类。
-你可以通过 `FastAPI` 使用所有的 Starlette 的功能。
+你可以通过 `FastAPI` 使用所有的 Starlette 的功能。
///
@@ -152,34 +167,6 @@ OpenAPI 为你的 API 定义 API 模式。该模式中包含了你的 API 发送
这个实例将是创建你所有 API 的主要交互对象。
-这个 `app` 同样在如下命令中被 `uvicorn` 所引用:
-
-
-
-```console
-$ uvicorn main:app --reload
-
-INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
-```
-
-
```console
-$ uvicorn main:app --reload
+$ 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: 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.
+ 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.
```