🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/virtual-environments.md`

Add Traditional Chinese translation for virtual-environments.md
為 virtual-environments（虛擬環境）一章加入翻譯

@@ -0,0 +1,844 @@
+# 虛擬環境
+
+當你在 Python 專案中工作時，你可能會需要使用一個**虛擬環境**（或類似的機制）來隔離你為每個專案安裝的套件。
+
+/// info
+
+如果你已經了解虛擬環境，知道如何建立和使用它們，你可以考慮跳過這一部分。🤓
+
+///
+
+/// tip
+
+**虛擬環境**和**環境變數**是不同的。
+
+**環境變數**是系統中的一個變數，可以被程式使用。
+
+**虛擬環境**是一個包含一些檔案的目錄。
+
+///
+
+/// info
+
+這個頁面將教你如何使用**虛擬環境**以及了解它們的工作原理。
+
+如果你計畫使用一個**可以為你管理一切的工具**（包括安裝 Python），試試 uv。
+
+///
+
+## 建立一個專案
+
+首先，為你的專案建立一個目錄。
+
+我（指原作者 —— 譯者注）通常會在我的主目錄下建立一個名為 `code` 的目錄。
+
+在這個目錄下，我再為每個專案建立一個目錄。
+
+

+
+```console
+// 進入主目錄
+$ cd
+// 建立一個用於存放所有程式碼專案的目錄
+$ mkdir code
+// 進入 code 目錄
+$ cd code
+// 建立一個用於存放這個專案的目錄
+$ mkdir awesome-project
+// 進入這個專案的目錄
+$ cd awesome-project
+```
+
+

+
+## 建立一個虛擬環境
+
+在開始一個 Python 專案的**第一時間**，**在你的專案內部**建立一個虛擬環境。
+
+/// tip
+
+你只需要**在每個專案中操作一次**，而不是每次工作時都操作。
+
+///
+
+//// tab | `venv`
+
+你可以使用 Python 自帶的 `venv` 模組來建立一個虛擬環境。
+
+

+
+```console
+$ python -m venv .venv
+```
+
+

+
+/// details | 上述命令的含義
+
+* `python`: 使用名為 `python` 的程式
+* `-m`: 以腳本的方式呼叫一個模組，我們將告訴它接下來使用哪個模組
+* `venv`: 使用名為 `venv` 的模組，這個模組通常隨 Python 一起安裝
+* `.venv`: 在新目錄 `.venv` 中建立虛擬環境
+
+///
+
+////
+
+//// tab | `uv`
+
+如果你安裝了 `uv`，你也可以使用它來建立一個虛擬環境。
+
+

+
+```console
+$ uv venv
+```
+
+

+
+/// tip
+
+預設情況下，`uv` 會在一個名為 `.venv` 的目錄中建立一個虛擬環境。
+
+但你可以透過傳遞一個額外的引數來自訂它，指定目錄的名稱。
+
+///
+
+////
+
+這個命令會在一個名為 `.venv` 的目錄中建立一個新的虛擬環境。
+
+/// details | `.venv`，或是其他名稱
+
+你可以在不同的目錄下建立虛擬環境，但通常我們會把它命名為 `.venv`。
+
+///
+
+## 啟動虛擬環境
+
+啟動新的虛擬環境來確保你運行的任何 Python 指令或安裝的套件都能使用到它。
+
+/// tip
+
+**每次**開始一個**新的終端會話**來在這個專案工作時，你都需要執行這個操作。
+
+///
+
+//// tab | Linux, macOS
+
+

+
+```console
+$ source .venv/bin/activate
+```
+
+

+
+////
+
+//// tab | [NAME_REDACTED]
+
+

+
+```console
+$ .venv\Scripts\Activate.ps1
+```
+
+

+
+////
+
+//// tab | [NAME_REDACTED]
+
+或者，如果你在 Windows 上使用 Bash（例如 [NAME_REDACTED]）：
+
+

+
+```console
+$ source .venv/Scripts/activate
+```
+
+

+
+////
+
+/// tip
+
+每次你在這個環境中安裝一個**新的套件**時，都需要**重新啟動**這個環境。
+
+這麼做確保了當你使用一個由這個套件安裝的**終端（CLI）程式**時，你使用的是你的虛擬環境中的程式，而不是全域安裝、可能版本不同的程式。
+
+///
+
+## 檢查虛擬環境是否啟動
+
+檢查虛擬環境是否啟動（前面的指令是否生效）。
+
+/// tip
+
+這是**非必需的**，但這是一個很好的方法，可以**檢查**一切是否按預期工作，以及你是否使用了你打算使用的虛擬環境。
+
+///
+
+//// tab | Linux, macOS, [NAME_REDACTED]
+
+

+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+

+
+如果它顯示了在你專案（在這個例子中是 `awesome-project`）的 `.venv/bin/python` 中的 `python` 二進位檔案，那麼它就生效了。🎉
+
+////
+
+//// tab | [NAME_REDACTED]
+
+

+
+```console
+$ Get-Command python
+
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+

+
+如果它顯示了在你專案（在這個例子中是 `awesome-project`）的 `.venv\Scripts\python` 中的 `python` 二進位檔案，那麼它就生效了。🎉
+
+////
+
+## 升級 `pip`
+
+/// tip
+
+如果你使用 `uv` 來安裝內容，而不是 `pip`，那麼你就不需要升級 `pip`。😎
+
+///
+
+如果你使用 `pip` 來安裝套件（它是 Python 的預設元件），你應該將它**升級**到最新版本。
+
+在安裝套件時出現的許多奇怪的錯誤都可以透過先升級 `pip` 來解決。
+
+/// tip
+
+通常你只需要在建立虛擬環境後**執行一次**這個操作。
+
+///
+
+確保虛擬環境是啟動的（使用上面的指令），然後運行：
+
+

+
+```console
+$ python -m pip install --upgrade pip
+
+---> 100%
+```
+
+

+
+## 加入 `.gitignore`
+
+如果你使用 **Git**（這是你應該使用的），加入一個 `.gitignore` 檔案來排除你的 `.venv` 中的所有內容。
+
+/// tip
+
+如果你使用 `uv` 來建立虛擬環境，它會自動為你完成這個操作，你可以跳過這一步。😎
+
+///
+
+/// tip
+
+通常你只需要在建立虛擬環境後**執行一次**這個操作。
+
+///
+
+

+
+```console
+$ echo "*" > .venv/.gitignore
+```
+
+

+
+/// details | 上述指令的含義
+
+-   `echo "*"`: 將在終端中「顯示」文本 `*`（接下來的部分會對這個操作進行一些修改）
+-   `>`: 使左邊的指令顯示到終端的任何內容實際上都不會被顯示，而是會被寫入到右邊的檔案中
+-   `.gitignore`: 被寫入文本的檔案的名稱
+
+而 `*` 對於 Git 來說意味著「所有內容」。所以，它會忽略 `.venv` 目錄中的所有內容。
+
+該指令會建立一個名為 .gitignore 的檔案，內容如下：
+
+```gitignore
+*
+```
+
+///
+
+## 安裝套件
+
+在啟用虛擬環境後，你可以在其中安裝套件。
+
+/// tip
+
+當你需要安裝或升級套件時，執行本操作**一次**；
+
+如果你需要再升級版本或新增套件，你可以**再次執行此操作**。
+
+///
+
+### 直接安裝套件
+
+如果你急於安裝，不想使用檔案來聲明專案的套件依賴，你可以直接安裝它們。
+
+/// tip
+
+將程式所需的套件及其版本放在檔案中（例如 `requirements.txt` 或 `pyproject.toml`）是個好（而且非常好）的主意。
+
+///
+
+//// tab | `pip`
+
+

+
+```console
+$ pip install "fastapi[standard]"
+
+---> 100%
+```
+
+

+
+////
+
+//// tab | `uv`
+
+如果你有 `uv`:
+
+

+
+```console
+$ uv pip install "fastapi[standard]"
+---> 100%
+```
+
+

+
+////
+
+### 從 `requirements.txt` 安裝
+
+如果你有一個 `requirements.txt` 檔案，你可以使用它來安裝其中的套件。
+
+//// tab | `pip`
+
+

+
+```console
+$ pip install -r requirements.txt
+---> 100%
+```
+
+

+
+////
+
+//// tab | `uv`
+
+如果你有 `uv`:
+
+

+
+```console
+$ uv pip install -r requirements.txt
+---> 100%
+```
+
+

+
+////
+
+/// details | 關於 `requirements.txt`
+
+一個包含一些套件的 `requirements.txt` 檔案看起來應該是這樣的：
+
+```requirements.txt
+fastapi[standard]==0.113.0
+pydantic==2.8.0
+```
+
+///
+
+## 執行程式
+
+在啟用虛擬環境後，你可以執行你的程式，它將使用虛擬環境中的 Python 和你在其中安裝的套件。
+
+

+
+```console
+$ python main.py
+
+[NAME_REDACTED]
+```
+
+

+
+## 設定編輯器
+
+你可能會用到編輯器，請確保設定它使用你建立的相同虛擬環境（它可能會自動偵測到），以便你可以獲得自動完成和内嵌錯誤提示。
+
+例如：
+
+* VS Code
+* PyCharm
+
+/// tip
+
+通常你只需要在建立虛擬環境時執行此操作**一次**。
+
+///
+
+## 退出虛擬環境
+
+當你完成工作後，你可以**退出**虛擬環境。
+
+

+
+```console
+$ deactivate
+```
+
+

+
+這樣，當你執行 `python` 時它不會嘗試從已安裝套件的虛擬環境中執行。
+
+## 開始工作
+
+現在你已經準備好開始你的工作了。
+
+
+
+/// tip
+
+你想要理解上面的所有內容嗎？
+
+繼續閱讀。👇🤓
+
+///
+
+## 為什麼要使用虛擬環境
+
+你需要安裝 Python 才能使用 FastAPI。
+
+接下來，你需要**安裝** FastAPI 以及你想使用的其他**套件**。
+
+要安裝套件，你通常會使用隨 Python 一起提供的 `pip` 指令（或類似的替代工具）。
+
+然而，如果你直接使用 `pip`，套件將會安裝在你的**全域 Python 環境**中（即 Python 的全域安裝）。
+
+### 存在的問題
+
+那麼，在全域 Python 環境中安裝套件有什麼問題呢？
+
+有時候，你可能會開發許多不同的程式，而這些程式各自依賴於**不同的套件**；有些專案甚至需要依賴於**相同套件的不同版本**。😱
+
+例如，你可能會建立一個名為 `philosophers-stone` 的專案，這個程式依賴於另一個名為 **`harry` 的套件，並使用版本 `1`**。因此，你需要安裝 `harry`。
+
+```mermaid
+flowchart LR
+    stone(philosophers-stone) -->|需要| harry-1[harry v1]
+```
+
+然而，在此之後，你又建立了另一個名為 `prisoner-of-azkaban` 的專案，而這個專案也依賴於 `harry`，但需要的是 **`harry` 版本 `3`**。
+
+```mermaid
+flowchart LR
+    azkaban(prisoner-of-azkaban) --> |需要| harry-3[harry v3]
+```
+
+現在的問題是，如果你在全域環境中安裝套件而不是在本地**虛擬環境**中，你將面臨選擇安裝哪個版本的 `harry` 的困境。
+
+如果你想運行 `philosophers-stone`，你需要先安裝 `harry` 版本 `1`，例如：
+
+

+
+```console
+$ pip install "harry==1"
+```
+
+

+
+然後你會在全域 Python 環境中安裝 `harry` 版本 `1`。
+
+```mermaid
+flowchart LR
+    subgraph global[全域環境]
+        harry-1[harry v1]
+    end
+    subgraph stone-project[專案 philosophers-stone]
+        stone(philosophers-stone) -->|需要| harry-1
+    end
+```
+
+但如果你想運行 `prisoner-of-azkaban`，你需要解除安裝 `harry` 版本 `1` 並安裝 `harry` 版本 `3`（或者只要你安裝版本 `3`，版本 `1` 就會自動移除）。
+
+

+
+```console
+$ pip install "harry==3"
+```
+
+

+
+於是，你在全域 Python 環境中安裝了 `harry` 版本 `3`。
+
+如果你再次嘗試運行 `philosophers-stone`，很可能會**無法正常運作**，因為它需要的是 `harry` 版本 `1`。
+
+```mermaid
+flowchart LR
+    subgraph global[全域環境]
+        harry-1[<strike>harry v1</strike>]
+        style harry-1 fill:#ccc,stroke-dasharray: 5 5
+        harry-3[harry v3]
+    end
+    subgraph stone-project[專案 philosophers-stone]
+        stone(philosophers-stone) -.-x|⛔| harry-1
+    end
+    subgraph azkaban-project[專案 prisoner-of-azkaban]
+        azkaban(prisoner-of-azkaban) --> |需要| harry-3
+    end
+```
+
+/// tip
+
+Python 套件在推出**新版本**時通常會儘量**避免破壞性更改**，但最好還是要謹慎，在安裝新版本前進行測試，以確保一切能正常運行。
+
+///
+
+現在，想像一下如果有**許多**其他**套件**，它們都是你的**專案所依賴的**。這樣是非常難以管理的。你可能會發現有些專案使用了一些**不相容的套件版本**，而無法得知為什麼某些程式無法正常運作。
+
+此外，取決於你的操作系統（例如 Linux、Windows、macOS），它可能已經預先安裝了 Python。在這種情況下，它可能已經有一些系統所需的套件和特定版本。如果你在全域 Python 環境中安裝套件，可能會**破壞**某些隨作業系統一起安裝的程式。
+
+## 套件安裝在哪裡
+
+當你安裝 Python 時，它會在你的電腦中建立一些目錄並放置一些檔案。
+
+其中一些目錄專門用來存放你所安裝的所有套件。
+
+當你運行：
+
+

+
+```console
+// 先別去運行這個指令，這只是個示例 🤓
+$ pip install "fastapi[standard]"
+---> 100%
+```
+
+

+
+這會從 PyPI 下載一個壓縮檔案，其中包含 FastAPI 的程式碼。
+
+它還會**下載** FastAPI 所依賴的其他套件的檔案。
+
+接著，它會**解壓**所有這些檔案，並將它們放在你的電腦中的某個目錄中。
+
+預設情況下，這些下載和解壓的檔案會放置於隨 Python 安裝的目錄中，即**全域環境**。
+
+## 什麼是虛擬環境
+
+解決套件都安裝在全域環境中的問題方法是為你所做的每個專案使用一個**虛擬環境**。
+
+虛擬環境是一個**目錄**，與全域環境非常相似，你可以在其中針對某個專案安裝套件。
+
+這樣，每個專案都會有自己的虛擬環境（`.venv` 目錄），其中包含自己的套件。
+
+```mermaid
+flowchart TB
+    subgraph stone-project[專案 philosophers-stone]
+        stone(philosophers-stone) --->|需要| harry-1
+        subgraph venv1[.venv]
+            harry-1[harry v1]
+        end
+    end
+    subgraph azkaban-project[專案 prisoner-of-azkaban]
+        azkaban(prisoner-of-azkaban) --->|需要| harry-3
+        subgraph venv2[.venv]
+            harry-3[harry v3]
+        end
+    end
+    stone-project ~~~ azkaban-project
+```
+
+## 啟用虛擬環境意味著什麼
+
+當你啟用了虛擬環境，例如：
+
+//// tab | Linux, macOS
+
+

+
+```console
+$ source .venv/bin/activate
+```
+
+

+
+////
+
+//// tab | [NAME_REDACTED]
+
+

+
+```console
+$ .venv\Scripts\Activate.ps1
+```
+
+

+
+////
+
+//// tab | [NAME_REDACTED]
+
+或者如果你在 Windows 上使用 Bash（例如 [NAME_REDACTED]）：
+
+

+
+```console
+$ source .venv/Scripts/activate
+```
+
+

+
+////
+
+這個命令會建立或修改一些[環境變數](environment-variables.md){.internal-link target=_blank}，這些環境變數將在接下來的指令中可用。
+
+其中之一是 `PATH` 變數。
+
+/// tip
+
+你可以在 [環境變數](environment-variables.md#path-environment-variable){.internal-link target=_blank} 部分了解更多關於 `PATH` 環境變數的內容。
+
+///
+
+啟用虛擬環境會將其路徑 `.venv/bin`（在 Linux 和 macOS 上）或 `.venv\Scripts`（在 Windows 上）加入到 `PATH` 環境變數中。
+
+假設在啟用環境之前，`PATH` 變數看起來像這樣：
+
+//// tab | Linux, macOS
+
+```plaintext
+/usr/bin:/bin:/usr/sbin:/sbin
+```
+
+這意味著系統會在以下目錄中查找程式：
+
+* `/usr/bin`
+* `/bin`
+* `/usr/sbin`
+* `/sbin`
+
+////
+
+//// tab | Windows
+
+```plaintext
+C:\Windows\System32
+```
+
+這意味著系統會在以下目錄中查找程式：
+
+* `C:\Windows\System32`
+
+////
+
+啟用虛擬環境後，`PATH` 變數會變成這樣：
+
+//// tab | Linux, macOS
+
+```plaintext
+/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin
+```
+
+這意味著系統現在會首先在以下目錄中查找程式：
+
+```plaintext
+/home/user/code/awesome-project/.venv/bin
+```
+
+然後再在其他目錄中查找。
+
+因此，當你在終端機中輸入 `python` 時，系統會在以下目錄中找到 Python 程式：
+
+```plaintext
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+並使用這個。
+
+////
+
+//// tab | Windows
+
+```plaintext
+C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32
+```
+
+這意味著系統現在會首先在以下目錄中查找程式：
+
+```plaintext
+C:\Users\user\code\awesome-project\.venv\Scripts
+```
+
+然後再在其他目錄中查找。
+
+因此，當你在終端機中輸入 `python` 時，系統會在以下目錄中找到 Python 程式：
+
+```plaintext
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+並使用這個。
+
+////
+
+一個重要的細節是，虛擬環境路徑會被放在 `PATH` 變數的**開頭**。系統會在找到任何其他可用的 Python **之前**找到它。這樣，當你運行 `python` 時，它會使用**虛擬環境中的** Python，而不是任何其他 `python`（例如，全域環境中的 `python`）。
+
+啟用虛擬環境還會改變其他一些內容，但這是它所做的最重要的事情之一。
+
+## 檢查虛擬環境
+
+當你檢查虛擬環境是否啟動時，例如：
+
+//// tab | Linux, macOS, [NAME_REDACTED]
+
+

+
+```console
+$ which python
+
+/home/user/code/awesome-project/.venv/bin/python
+```
+
+

+
+////
+
+//// tab | [NAME_REDACTED]
+
+

+
+```console
+$ Get-Command python
+
+C:\Users\user\code\awesome-project\.venv\Scripts\python
+```
+
+

+
+////
+
+這表示將使用的 `python` 程式是**在虛擬環境中**的那一個。
+
+在 Linux 和 macOS 中使用 `which`，在 [NAME_REDACTED] 中使用 `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 <module>
+        import sirius
+```
+
+

+
+但如果你停用虛擬環境並啟用 `prisoner-of-askaban` 的新虛擬環境，那麼當你執行 `python` 時，它會使用 `prisoner-of-askaban` 中虛擬環境的 Python。
+
+

+
+```console
+$ cd ~/code/prisoner-of-azkaban
+
+// 你不需要在舊目錄中操作停用，你可以在任何地方操作停用，甚至在切換到另一個專案之後 😎
+$ deactivate
+
+// 啟用 prisoner-of-azkaban/.venv 中的虛擬環境 🚀
+$ source .venv/bin/activate
+
+// 現在當你執行 python 時，它會在這個虛擬環境中找到已安裝的 sirius 套件 ✨
+$ python main.py
+
+I solemnly swear 🐺
+```
+
+

+
+## 替代方案
+
+這是一個簡單的指南，幫助你入門並教會你如何理解一切**底層**的原理。
+
+有許多**替代方案**來管理虛擬環境、套件依賴（requirements）、專案。
+
+當你準備好並想要使用一個工具來**管理整個專案**、套件依賴、虛擬環境等，建議你嘗試 uv。
+
+`uv` 可以執行許多操作，它可以：
+
+* 為你**安裝 Python**，包括不同的版本
+* 為你的專案管理**虛擬環境**
+* 安裝**套件**
+* 為你的專案管理套件的**依賴和版本**
+* 確保你有一個**精確**的套件和版本集合來安裝，包括它們的依賴項，這樣你可以確保專案在生產環境中運行的狀態與開發時在你的電腦上運行的狀態完全相同，這被稱為**鎖定**
+* 還有很多其他功能
+
+## 結論
+
+如果你讀過並理解了所有這些，現在**你對虛擬環境的了解已超過許多開發者**。🤓
+
+未來當你為看起來複雜的問題除錯時，了解這些細節很可能會有所幫助，你會知道**它是如何在底層運作的**。😎

LGTM

我 review 時比較偷懶，同樣的問題只會留一次 comment，想請你再依先前的建議檢查全文是否還有同樣的問題

should be the last one

nice work!

how about 非必需的?

好的，已更改 :)

一般來說  `uninstall` 會翻譯成 `解除安裝` 或是 `移除` 比較常見?

好的，已修正

辛苦了

避免簡中用詞
```suggestion
如果你已經了解虛擬環境，知道如何建立和使用它們，你可以考慮跳過這一部分。🤓
```

```suggestion
* `-m`: 以腳本的方式呼叫一個模組，我們將告訴它接下來使用哪個模組
```

parameter 為參數、argument 為引數
```suggestion
但你可以通過傳遞一個額外的引數來自訂它，指定目錄的名稱。
```

「工作在」是否需要修正一下？

中文間不需空格
```suggestion
每次你在這個環境中安裝一個**新的套件**時，都需要**重新啟動**這個環境。
```

```suggestion
這麼做確保了當你使用一個由這個套件安裝的 **終端（<abbr title="命令列介面">CLI</abbr>）程式** 時，你使用的是你的虛擬環境中的程式，而不是全域安裝、可能版本不同的程式。
```

```suggestion
在安裝套件時出現的許多奇怪的錯誤都可以透過先升級 `pip` 來解決。
```

IDE 不是編輯器

inline 大多翻譯為「內嵌」、「行內」

- 這裡的幾個逗號不是中文慣用用法
- 後面備註好像不是很必要

中英文間要有空格
```suggestion
然而，在此之後，你又建立了另一個名為 `prisoner-of-azkaban` 的專案，而這個專案也依賴於 `harry`，但需要的是 **`harry` 版本 `3`**。
```

```suggestion
未來當你為看起來複雜的問題除錯時，了解這些細節很可能會有所幫助，你會知道**它是如何在底層運作的**。😎
```

好的，我改為了
```md
**每次**開始一個**新的終端會話**來在這個專案工作時，你都需要執行這個操作。
```

已刪去。中國大陸的開發者常會混用這兩個概念，在同時翻譯兩個語言的時候沒有注意到差異。

OK

「創建」一詞多次出現，要請你再檢查全文一遍

中文間不需空格、中文與英文間需要空格
```suggestion
這是**非必需的**，但這是一個很好的方法，可以**檢查**一切是否按預期工作，以及你是否使用了你打算使用的虛擬環境。
```

原來你同時發了兩邊的 PR 👍🏽

對的，我母語簡中，繁中這邊是參照術語對照表二次翻譯的，所以有一些不常見的非術語用詞可能疏漏了

搞定啦

```suggestion
### 直接安裝套件
```

OK done :)

好奇想請教你是參考哪一份對照表呢？
我自己是會參考這兩份（來自 [Python 文件繁中翻譯 repo wiki](https://github.com/[USER_REDACTED]n/python-docs-zh-tw/wiki/___%E8%A9%B2%E7%BF%BB%E6%88%90%E4%BB%80%E9%BA%BC%EF%BC%9F)）：
- [L10N Taiwan - 詞彙對照表](https://hackmd.io/[USER_REDACTED]/glossaries)
- [維基教科書 - 大陆台湾计算机术语对照表](https://zh.wikibooks.org/zh/%E5%A4%A7%E9%99%86%E5%8F%B0%E6%B9%BE%E8%AE%A1%E7%AE%97%E6%9C%BA%E6%9C%AF%E8%AF%AD%E5%AF%B9%E7%85%A7%E8%A1%A8)

The last one you listed

This is not rendering properly. Can you check and fix it? (you can validate with the preview)
Thank you!

Okey... It should be able to work now 🤔


🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/environment-variables.md`

Add Traditional Chinese translation for docs/zh-hant/docs/environment-variables.md
為 environment-variables.md (環境變數) 章節添加正體中文翻譯

@@ -0,0 +1,298 @@
+# 環境變數
+
+/// tip
+
+如果你已經知道什麼是「環境變數」並且知道如何使用它們，你可以放心跳過這一部分。
+
+///
+
+環境變數（也稱為「**env var**」）是一個獨立於 Python 程式碼**之外**的變數，它存在於**作業系統**中，可以被你的 Python 程式碼（或其他程式）讀取。
+
+環境變數對於處理應用程式**設定**（作為 Python **安裝**的一部分等方面）非常有用。
+
+## 建立和使用環境變數
+
+你在 **shell（終端機）**中就可以**建立**和使用環境變數，並不需要用到 Python：
+
+//// tab | Linux, macOS, [NAME_REDACTED]
+
+

+
+```console
+// 你可以使用以下指令建立一個名為 MY_NAME 的環境變數
+$ export MY_NAME="[NAME_REDACTED]"
+
+// 然後，你可以在其他程式中使用它，例如
+$ echo "Hello $MY_NAME"
+
+[NAME_REDACTED]
+```
+
+

+
+////
+
+//// tab | [NAME_REDACTED]
+
+

+
+```console
+// 建立一個名為 MY_NAME 的環境變數
+$ $Env:MY_NAME = "[NAME_REDACTED]"
+
+// 在其他程式中使用它，例如
+$ echo "Hello $Env:MY_NAME"
+
+[NAME_REDACTED]
+```
+
+

+
+////
+
+## 在 Python 中讀取環境變數
+
+你也可以在 Python **之外**的終端機中建立環境變數（或使用其他方法），然後在 Python 中**讀取**它們。
+
+例如，你可以建立一個名為 `main.py` 的檔案，其中包含以下內容：
+
+```Python hl_lines="3"
+import os
+
+name = os.getenv("MY_NAME", "World")
+print(f"Hello {name} from Python")
+```
+
+/// tip
+
+第二個參數是 `os.getenv()` 的預設回傳值。
+
+如果沒有提供，預設值為 `None`，這裡我們提供 `"World"` 作為預設值。
+
+///
+
+然後你可以呼叫這個 Python 程式：
+
+//// tab | Linux, macOS, [NAME_REDACTED]
+
+

+
+```console
+// 這裡我們還沒有設定環境變數
+$ python main.py
+
+// 因為我們沒有設定環境變數，所以我們得到的是預設值
+
+[NAME_REDACTED] from Python
+
+// 但是如果我們事先建立過一個環境變數
+$ export MY_NAME="[NAME_REDACTED]"
+
+// 然後再次呼叫程式
+$ python main.py
+
+// 現在就可以讀取到環境變數了
+
+[NAME_REDACTED] from Python
+```
+
+

+
+////
+
+//// tab | [NAME_REDACTED]
+
+

+
+```console
+// 這裡我們還沒有設定環境變數
+$ python main.py
+
+// 因為我們沒有設定環境變數，所以我們得到的是預設值
+
+[NAME_REDACTED] from Python
+
+// 但是如果我們事先建立過一個環境變數
+$ $Env:MY_NAME = "[NAME_REDACTED]"
+
+// 然後再次呼叫程式
+$ python main.py
+
+// 現在就可以讀取到環境變數了
+
+[NAME_REDACTED] from Python
+```
+
+

+
+////
+
+由於環境變數可以在程式碼之外設定，但可以被程式碼讀取，並且不必與其他檔案一起儲存（提交到 `git`），因此通常用於配置或**設定**。
+
+你還可以為**特定的程式呼叫**建立特定的環境變數，該環境變數僅對該程式可用，且僅在其執行期間有效。
+
+要實現這一點，只需在同一行內（程式本身之前）建立它：
+
+

+
+```console
+// 在這個程式呼叫的同一行中建立一個名為 MY_NAME 的環境變數
+$ MY_NAME="[NAME_REDACTED]" python main.py
+
+// 現在就可以讀取到環境變數了
+
+[NAME_REDACTED] from Python
+
+// 在此之後這個環境變數將不再存在
+$ python main.py
+
+[NAME_REDACTED] from Python
+```
+
+

+
+/// tip
+
+你可以在 The Twelve-Factor App: 配置中了解更多資訊。
+
+///
+
+## 型別和驗證
+
+這些環境變數只能處理**文字字串**，因為它們是位於 Python 範疇之外的，必須與其他程式和作業系統的其餘部分相容（甚至與不同的作業系統相容，如 Linux、Windows、macOS）。
+
+這意味著從環境變數中讀取的**任何值**在 Python 中都將是一個 `str`，任何型別轉換或驗證都必須在程式碼中完成。
+
+你將在[進階使用者指南 - 設定和環境變數](./advanced/settings.md)中了解更多關於使用環境變數處理**應用程式設定**的資訊。
+
+## `PATH` 環境變數
+
+有一個**特殊的**環境變數稱為 **`PATH`**，作業系統（Linux、macOS、Windows）用它來查找要執行的程式。
+
+`PATH` 變數的值是一個長字串，由 Linux 和 macOS 上的冒號 `:` 分隔的目錄組成，而在 Windows 上則是由分號 `;` 分隔的。
+
+例如，`PATH` 環境變數可能如下所示：
+
+//// tab | Linux, macOS
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
+```
+
+這意味著系統應該在以下目錄中查找程式：
+
+-   `/usr/local/bin`
+-   `/usr/bin`
+-   `/bin`
+-   `/usr/sbin`
+-   `/sbin`
+
+////
+
+//// tab | Windows
+
+```plaintext
+C:\[NAME_REDACTED]\Python312\Scripts;C:\[NAME_REDACTED]\Python312;C:\Windows\System32
+```
+
+這意味著系統應該在以下目錄中查找程式：
+
+-   `C:\[NAME_REDACTED]\Python312\Scripts`
+-   `C:\[NAME_REDACTED]\Python312`
+-   `C:\Windows\System32`
+
+////
+
+當你在終端機中輸入一個**指令**時，作業系統會在 `PATH` 環境變數中列出的**每個目錄**中**查找**程式。
+
+例如，當你在終端機中輸入 `python` 時，作業系統會在該列表中的**第一個目錄**中查找名為 `python` 的程式。
+
+如果找到了，那麼作業系統將**使用它**；否則，作業系統會繼續在**其他目錄**中查找。
+
+### 安裝 Python 並更新 `PATH`
+
+安裝 Python 時，可能會詢問你是否要更新 `PATH` 環境變數。
+
+//// tab | Linux, macOS
+
+假設你安裝了 Python，並將其安裝在目錄 `/opt/custompython/bin` 中。
+
+如果你選擇更新 `PATH` 環境變數，那麼安裝程式會將 `/opt/custompython/bin` 加入到 `PATH` 環境變數中。
+
+它看起來大致會是這樣：
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin
+```
+
+如此一來，當你在終端機輸入 `python` 時，系統會在 `/opt/custompython/bin` 中找到 Python 程式（最後一個目錄）並使用它。
+
+////
+
+//// tab | Windows
+
+假設你安裝了 Python，並將其安裝在目錄 `C:\opt\custompython\bin` 中。
+
+如果你選擇更新 `PATH` 環境變數（在 Python 安裝程式中，這個選項是名為 `Add Python x.xx to PATH` 的勾選框——譯者註），那麼安裝程式會將 `C:\opt\custompython\bin` 加入到 `PATH` 環境變數中。
+
+```plaintext
+C:\[NAME_REDACTED]\Python312\Scripts;C:\[NAME_REDACTED]\Python312;C:\Windows\System32;C:\opt\custompython\bin
+```
+
+如此一來，當你在終端機輸入 `python` 時，系統會在 `C:\opt\custompython\bin` 中找到 Python 程式（最後一個目錄）並使用它。
+
+////
+
+因此，如果你輸入：
+
+

+
+```console
+$ python
+```
+
+

+
+//// tab | Linux, macOS
+
+系統會在 `/opt/custompython/bin` 中**找到** `python` 程式並執行它。
+
+這大致等同於輸入以下指令：
+
+

+
+```console
+$ /opt/custompython/bin/python
+```
+
+

+
+////
+
+//// tab | Windows
+
+系統會在 `C:\opt\custompython\bin\python` 中**找到** `python` 程式並執行它。
+
+這大致等同於輸入以下指令：
+
+

+
+```console
+$ C:\opt\custompython\bin\python
+```
+
+

+
+////
+
+當學習[虛擬環境](virtual-environments.md)時，這些資訊將會很有用。
+
+## 結論
+
+透過這個教學，你應該對**環境變數**是什麼以及如何在 Python 中使用它們有了基本的了解。
+
+你也可以在環境變數 - 維基百科 (Wikipedia for [NAME_REDACTED]) 中了解更多關於它們的資訊。
+
+在許多情況下，環境變數的用途和適用性可能不會立刻顯現。但是在開發過程中，它們會在許多不同的場景中出現，因此瞭解它們是非常必要的。
+
+例如，你在接下來的[虛擬環境](virtual-environments.md)章節中將需要這些資訊。

LGTM

```suggestion
你在 **shell（終端機）**中就可以**建立**和使用環境變數，並不需要用到 Python：
```

```suggestion
第二個參數是 <a href="https://docs.python.org/zh-tw/3.8/library/os.html#os.getenv" class="external-link" target="_blank">`os.getenv()`</a> 的預設回傳值。
```
「返回」是簡中用語，「回傳」是繁中，可以參考[這裡](https://zh.wikibooks.org/zh-tw/%E5%A4%A7%E9%99%86%E5%8F%B0%E6%B9%BE%E8%AE%A1%E7%AE%97%E6%9C%BA%E6%9C%AF%E8%AF%AD%E5%AF%B9%E7%85%A7%E8%A1%A8)。

```suggestion
由於環境變數可以在程式碼之外設定，但可以被程式碼讀取，並且不必與其他檔案一起儲存（提交到 `git`），因此通常用於配置或**設定**。
```

```suggestion
要實現這一點，可以在程式執行前的同一行直接建立環境變數：
```
這樣會不會比較順？

```suggestion
// 現在就可以讀取到環境變數了
```

```suggestion
// 在此之後這個環境變數將不再存在
```

```suggestion
你可以在 <a href="https://12factor.net/zh_cn/config" class="external-link" target="_blank">The Twelve-Factor App: 配置</a>中了解更多資訊。
```

```suggestion
## 型別和驗證
```
「類型」是簡中用法，「型別」是繁中用法。

```suggestion
這意味著從環境變數中讀取的**任何值**在 Python 中都將是一個 `str`，任何型別轉換或驗證都必須在程式碼中完成。
```

```suggestion
如果你選擇更新 `PATH` 環境變數，那麼安裝程式會將 `/opt/custompython/bin` 加入到 `PATH` 環境變數中。
```
[這裡](https://zh.wikibooks.org/zh-tw/%E5%A4%A7%E9%99%86%E5%8F%B0%E6%B9%BE%E8%AE%A1%E7%AE%97%E6%9C%BA%E6%9C%AF%E8%AF%AD%E5%AF%B9%E7%85%A7%E8%A1%A8)顯示「添加」是簡中用法。

```suggestion
如果你選擇更新 `PATH` 環境變數（在 Python 安裝程式中，這個選項是名為 `Add Python x.xx to PATH` 的勾選框——譯者註），那麼安裝程式會將 `C:\opt\custompython\bin` 加入到 `PATH` 環境變數中。
```

```suggestion
環境變數對於處理應用程式**設定**（例如作為 Python **安裝**的一部分等）非常有用。
```
這樣會不會比較順？

這麼做我擔心存在更改原文含義的嫌疑：

> Environment variables could be useful for handling application settings, as part of the installation of Python, etc.

這麼做我擔心存在更改原文含義的嫌疑：

> To do that, create it right before the program itself, on the same line:

另外我覺得原先的表達更為清晰，盡量避免長難句也是技術文檔翻譯需要重視的地方。這可能是一個仁者見仁，智者見智的問題。

```suggestion
要實現這一點，只需在同一行內（程式本身之前）建立它：
```
理解，那請問是否能修改成這樣？因為「頓號、」通常是在前後句子性質相同才會使用。

```suggestion
環境變數對於處理應用程式**設定**（作為 Python **安裝**的一部分等方面）非常有用。
```
理解，那是否能修改成這樣？

你是正確的，但是這麼做必要性不高。無論哪一種譯文都不會影響句子的理解。原文中本就使用了並列的句式，在沒有明顯謬誤的情況下我們沒有必要在翻譯時修改原作者的構思邏輯。
稍後我会併入你的修改。

好的。同上。


🌐 Add Chinese translation for `docs/zh/docs/environment-variables.md`

Add Chinese translation for environment-variables.md
为 environment-variables.md (环境变量) 一章添加翻译

@@ -0,0 +1,298 @@
+# 环境变量
+
+/// tip
+
+如果你已经知道什么是“环境变量”并且知道如何使用它们，你可以放心跳过这一部分。
+
+///
+
+环境变量（也称为“**env var**”）是一个独立于 Python 代码**之外**的变量，它存在于**操作系统**中，可以被你的 Python 代码（或其他程序）读取。
+
+环境变量对于处理应用程序**设置**、作为 Python **安装**的一部分等方面非常有用。
+
+## 创建和使用环境变量
+
+你在 **shell（终端）**中就可以**创建**和使用环境变量，并不需要用到 Python：
+
+//// tab | Linux, macOS, [NAME_REDACTED]
+
+

+
+```console
+// 你可以使用以下命令创建一个名为 MY_NAME 的环境变量
+$ export MY_NAME="[NAME_REDACTED]"
+
+// 然后，你可以在其他程序中使用它，例如
+$ echo "Hello $MY_NAME"
+
+[NAME_REDACTED]
+```
+
+

+
+////
+
+//// tab | [NAME_REDACTED]
+
+

+
+```console
+// 创建一个名为 MY_NAME 的环境变量
+$ $Env:MY_NAME = "[NAME_REDACTED]"
+
+// 在其他程序中使用它，例如
+$ echo "Hello $Env:MY_NAME"
+
+[NAME_REDACTED]
+```
+
+

+
+////
+
+## 在 Python 中读取环境变量
+
+你也可以在 Python **之外**的终端中创建环境变量（或使用任何其他方法），然后在 Python 中**读取**它们。
+
+例如，你可以创建一个名为 `main.py` 的文件，其中包含以下内容：
+
+```Python hl_lines="3"
+import os
+
+name = os.getenv("MY_NAME", "World")
+print(f"Hello {name} from Python")
+```
+
+/// tip
+
+第二个参数是 `os.getenv()` 的默认返回值。
+
+如果没有提供，默认值为 `None`，这里我们提供 `"World"` 作为默认值。
+
+///
+
+然后你可以调用这个 Python 程序：
+
+//// tab | Linux, macOS, [NAME_REDACTED]
+
+

+
+```console
+// 这里我们还没有设置环境变量
+$ python main.py
+
+// 因为我们没有设置环境变量，所以我们得到的是默认值
+
+[NAME_REDACTED] from Python
+
+// 但是如果我们事先创建过一个环境变量
+$ export MY_NAME="[NAME_REDACTED]"
+
+// 然后再次调用程序
+$ python main.py
+
+// 现在就可以读取到环境变量了
+
+[NAME_REDACTED] from Python
+```
+
+

+
+////
+
+//// tab | [NAME_REDACTED]
+
+

+
+```console
+// 这里我们还没有设置环境变量
+$ python main.py
+
+// 因为我们没有设置环境变量，所以我们得到的是默认值
+
+[NAME_REDACTED] from Python
+
+// 但是如果我们事先创建过一个环境变量
+$ $Env:MY_NAME = "[NAME_REDACTED]"
+
+// 然后再次调用程序
+$ python main.py
+
+// 现在就可以读取到环境变量了
+
+[NAME_REDACTED] from Python
+```
+
+

+
+////
+
+由于环境变量可以在代码之外设置、但可以被代码读取，并且不必与其他文件一起存储（提交到 `git`），因此通常用于配置或**设置**。
+
+你还可以为**特定的程序调用**创建特定的环境变量，该环境变量仅对该程序可用，且仅在其运行期间有效。
+
+要实现这一点，只需在同一行内、程序本身之前创建它：
+
+

+
+```console
+// 在这个程序调用的同一行中创建一个名为 MY_NAME 的环境变量
+$ MY_NAME="[NAME_REDACTED]" python main.py
+
+// 现在就可以读取到环境变量了
+
+[NAME_REDACTED] from Python
+
+// 在此之后这个环境变量将不会依然存在
+$ python main.py
+
+[NAME_REDACTED] from Python
+```
+
+

+
+/// tip
+
+你可以在 The Twelve-Factor App: 配置中了解更多信息。
+
+///
+
+## 类型和验证
+
+这些环境变量只能处理**文本字符串**，因为它们是处于 Python 范畴之外的，必须与其他程序和操作系统的其余部分兼容（甚至与不同的操作系统兼容，如 Linux、Windows、macOS）。
+
+这意味着从环境变量中读取的**任何值**在 Python 中都将是一个 `str`，任何类型转换或验证都必须在代码中完成。
+
+你将在[高级用户指南 - 设置和环境变量](./advanced/settings.md)中了解更多关于使用环境变量处理**应用程序设置**的信息。
+
+## `PATH` 环境变量
+
+有一个**特殊的**环境变量称为 **`PATH`**，操作系统（Linux、macOS、Windows）用它来查找要运行的程序。
+
+`PATH` 变量的值是一个长字符串，由 Linux 和 macOS 上的冒号 `:` 分隔的目录组成，而在 Windows 上则是由分号 `;` 分隔的。
+
+例如，`PATH` 环境变量可能如下所示：
+
+//// tab | Linux, macOS
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
+```
+
+这意味着系统应该在以下目录中查找程序：
+
+-   `/usr/local/bin`
+-   `/usr/bin`
+-   `/bin`
+-   `/usr/sbin`
+-   `/sbin`
+
+////
+
+//// tab | Windows
+
+```plaintext
+C:\[NAME_REDACTED]\Python312\Scripts;C:\[NAME_REDACTED]\Python312;C:\Windows\System32
+```
+
+这意味着系统应该在以下目录中查找程序：
+
+-   `C:\[NAME_REDACTED]\Python312\Scripts`
+-   `C:\[NAME_REDACTED]\Python312`
+-   `C:\Windows\System32`
+
+////
+
+当你在终端中输入一个**命令**时，操作系统会在 `PATH` 环境变量中列出的**每个目录**中**查找**程序。
+
+例如，当你在终端中输入 `python` 时，操作系统会在该列表中的**第一个目录**中查找名为 `python` 的程序。
+
+如果找到了，那么操作系统将**使用它**；否则，操作系统会继续在**其他目录**中查找。
+
+### 安装 Python 和更新 `PATH`
+
+安装 Python 时，可能会询问你是否要更新 `PATH` 环境变量。
+
+//// tab | Linux, macOS
+
+假设你安装 Python 并最终将其安装在了目录 `/opt/custompython/bin` 中。
+
+如果你同意更新 `PATH` 环境变量，那么安装程序将会将 `/opt/custompython/bin` 添加到 `PATH` 环境变量中。
+
+它看起来大概会像这样：
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin
+```
+
+如此一来，当你在终端中输入 `python` 时，系统会在 `/opt/custompython/bin` 中找到 Python 程序（最后一个目录）并使用它。
+
+////
+
+//// tab | Windows
+
+假设你安装 Python 并最终将其安装在了目录 `C:\opt\custompython\bin` 中。
+
+如果你同意更新 `PATH` 环境变量 (在 Python 安装程序中，这个操作是名为 `Add Python x.xx to PATH` 的复选框 —— 译者注)，那么安装程序将会将 `C:\opt\custompython\bin` 添加到 `PATH` 环境变量中。
+
+```plaintext
+C:\[NAME_REDACTED]\Python312\Scripts;C:\[NAME_REDACTED]\Python312;C:\Windows\System32;C:\opt\custompython\bin
+```
+
+如此一来，当你在终端中输入 `python` 时，系统会在 `C:\opt\custompython\bin` 中找到 Python 程序（最后一个目录）并使用它。
+
+////
+
+因此，如果你输入：
+
+

+
+```console
+$ python
+```
+
+

+
+//// tab | Linux, macOS
+
+系统会在 `/opt/custompython/bin` 中**找到** `python` 程序并运行它。
+
+这和输入以下命令大致等价：
+
+

+
+```console
+$ /opt/custompython/bin/python
+```
+
+

+
+////
+
+//// tab | Windows
+
+系统会在 `C:\opt\custompython\bin\python` 中**找到** `python` 程序并运行它。
+
+这和输入以下命令大致等价：
+
+

+
+```console
+$ C:\opt\custompython\bin\python
+```
+
+

+
+////
+
+当学习[虚拟环境](virtual-environments.md)时，这些信息将会很有用。
+
+## 结论
+
+通过这个教程，你应该对**环境变量**是什么以及如何在 Python 中使用它们有了基本的了解。
+
+你也可以在环境变量 - 维基百科 (Wikipedia for [NAME_REDACTED]) 中了解更多关于它们的信息。
+
+在许多情况下，环境变量的用途和适用性并不是很明显。但是在开发过程中，它们会在许多不同的场景中出现，因此了解它们是很有必要的。
+
+例如，你将在下一节关于[虚拟环境](virtual-environments.md)中需要这些信息。

**环墍变量** ==> **环境变量**


🌐 Add Portuguese translation for `docs/pt/docs/advanced/path-operation-advanced-configuration.md`

@@ -0,0 +1,212 @@
+# Configuração Avançada da Operação de Rota
+
+## operationId do OpenAPI
+
+/// warning | Aviso
+
+Se você não é um "especialista" no OpenAPI, você provavelmente não precisa disso.
+
+///
+
+Você pode definir o `operationId` do OpenAPI que será utilizado na sua *operação de rota* com o parâmetro `operation_id`.
+
+Você precisa ter certeza que ele é único para cada operação.
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *}
+
+### Utilizando o nome da *função de operação de rota* como o operationId
+
+Se você quiser utilizar o nome das funções da sua API como `operationId`s, você pode iterar sobre todos esses nomes e sobrescrever o `operationId` em  cada *operação de rota* utilizando o `APIRoute.name` dela.
+
+Você deve fazer isso depois de adicionar todas as suas *operações de rota*.
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2,12:21,24] *}
+
+/// tip | Dica
+
+Se você chamar `app.openapi()` manualmente, os `operationId`s devem ser atualizados antes dessa chamada.
+
+///
+
+/// warning | Aviso
+
+Se você fizer isso, você tem que ter certeza de que cada uma das suas *funções de operação de rota* tem um nome único.
+
+Mesmo que elas estejam em módulos (arquivos Python) diferentes.
+
+///
+
+## Excluir do OpenAPI
+
+Para excluir uma *operação de rota* do esquema OpenAPI gerado (e por consequência, dos sistemas de documentação automáticos), utilize o parâmetro `include_in_schema` e defina ele como `False`:
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *}
+
+## Descrição avançada a partir de docstring
+
+Você pode limitar as linhas utilizadas a partir de uma docstring de uma *função de operação de rota* para o OpenAPI.
+
+Adicionar um `\f` (um caractere de escape para alimentação de formulário) faz com que o **FastAPI** restrinja a saída utilizada pelo OpenAPI até esse ponto.
+
+Ele não será mostrado na documentação, mas outras ferramentas (como o Sphinx) serão capazes de utilizar o resto do texto.
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *}
+
+## [NAME_REDACTED]
+
+Você provavelmente já viu como declarar o `response_model` e `status_code` para uma *operação de rota*.
+
+Isso define os metadados sobre a resposta principal da *operação de rota*.
+
+Você também pode declarar respostas adicionais, com seus modelos, códigos de status, etc.
+
+Existe um capítulo inteiro da nossa documentação sobre isso, você pode ler em [[NAME_REDACTED] no OpenAPI](additional-responses.md){.internal-link target=_blank}.
+
+## Extras do OpenAPI
+
+Quando você declara uma *operação de rota* na sua aplicação, o **FastAPI** irá gerar os metadados relevantes da *operação de rota* automaticamente para serem incluídos no esquema do OpenAPI.
+
+/// note | Nota
+
+Na especificação do OpenAPI, isso é chamado de um Objeto de Operação.
+
+///
+
+Ele possui toda a informação sobre a *operação de rota* e é usado para gerar a documentação automaticamente.
+
+Ele inclui os atributos `tags`, `parameters`, `requestBody`, `responses`, etc.
+
+Esse esquema específico para uma *operação de rota* normalmente é gerado automaticamente pelo **FastAPI**, mas você também pode estender ele.
+
+/// tip | Dica
+
+Esse é um ponto de extensão de baixo nível.
+
+Caso você só precise declarar respostas adicionais, uma forma conveniente de fazer isso é com [[NAME_REDACTED] no OpenAPI](additional-responses.md){.internal-link target=_blank}.
+
+///
+
+Você pode estender o esquema do OpenAPI para uma *operação de rota* utilizando o parâmetro `openapi_extra`.
+
+### Extensões do OpenAPI
+
+Esse parâmetro `openapi_extra` pode ser útil, por exemplo, para declarar [Extensões do OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions):
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial005.py hl[6] *}
+
+Se você abrir os documentos criados automaticamente para a API, sua extensão aparecerá no final da *operação de rota* específica.
+
+
+
+E se você olhar o esquema OpenAPI resultante (na rota `/openapi.json` da sua API), você verá que a sua extensão também faz parte da *operação de rota* específica:
+
+```JSON hl_lines="22"
+{
+    "openapi": "3.1.0",
+    "info": {
+        "title": "FastAPI",
+        "version": "0.1.0"
+    },
+    "paths": {
+        "/items/": {
+            "get": {
+                "summary": "[NAME_REDACTED]",
+                "operationId": "read_items_items__get",
+                "responses": {
+                    "200": {
+                        "description": "[NAME_REDACTED]",
+                        "content": {
+                            "application/json": {
+                                "schema": {}
+                            }
+                        }
+                    }
+                },
+                "x-aperture-labs-portal": "blue"
+            }
+        }
+    }
+}
+```
+
+### Esquema de *operação de rota* do OpenAPI personalizado
+
+O dicionário em `openapi_extra` vai ter todos os seus níveis mesclados dentro do esquema OpenAPI gerado automaticamente para a *operação de rota*.
+
+Então, você pode adicionar dados extras para o esquema gerado automaticamente.
+
+Por exemplo, você poderia optar por ler e validar a requisição com seu próprio código, sem utilizar funcionalidades automatizadas do FastAPI com o Pydantic, mas você ainda pode quere definir a requisição no esquema OpenAPI.
+
+Você pode fazer isso com `openapi_extra`:
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial006.py hl[19:36,39:40] *}
+
+Nesse exemplo, nós não declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisição não está nem mesmo analisado como JSON, ele é lido diretamente como `bytes` e a função `magic_data_reader()` seria a responsável por analisar ele de alguma forma.
+
+De toda forma, nós podemos declarar o esquema esperado para o corpo da requisição.
+
+### Tipo de conteúdo do OpenAPI personalizado
+
+Utilizando esse mesmo truque, você pode utilizar um modelo Pydantic para definir o esquema JSON que é então incluído na seção do esquema personalizado do OpenAPI na *operação de rota*.
+
+E você pode fazer isso até mesmo quando os dados da requisição não seguem o formato JSON.
+
+Por exemplo, nesta aplicação nós não usamos a funcionalidade integrada ao FastAPI de extrair o esquema JSON dos modelos Pydantic nem a validação automática do JSON. Na verdade, estamos declarando o tipo do conteúdo da requisição como YAML, em vez de JSON:
+
+//// tab | Pydantic v2
+
+```Python hl_lines="17-22  24"
+{!> ../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
+```
+
+////
+
+//// tab | Pydantic v1
+
+```Python hl_lines="17-22  24"
+{!> ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py!}
+```
+
+////
+
+/// info | Informação
+
+Na versão 1 do Pydantic, o método para obter o esquema JSON de um modelo é `Item.schema()`, na versão 2 do Pydantic, o método é `Item.model_json_schema()`
+
+///
+
+Entretanto, mesmo que não utilizemos a funcionalidade integrada por padrão, ainda estamos usando um modelo Pydantic para gerar um esquema JSON manualmente para os dados que queremos receber no formato YAML.
+
+Então utilizamos a requisição diretamente, e extraímos o corpo como `bytes`. Isso significa que o FastAPI não vai sequer tentar analisar o corpo da requisição como JSON.
+
+E então no nosso código, nós analisamos o conteúdo YAML diretamente, e estamos utilizando o mesmo modelo Pydantic para validar o conteúdo YAML:
+
+//// tab | Pydantic v2
+
+```Python hl_lines="26-33"
+{!> ../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
+```
+
+////
+
+//// tab | Pydantic v1
+
+```Python hl_lines="26-33"
+{!> ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py!}
+```
+
+////
+
+/// info | Informação
+
+Na versão 1 do Pydantic, o método para analisar e validar um objeto era `Item.parse_obj()`, na versão 2 do Pydantic, o método é chamado de `Item.model_validate()`.
+
+///
+
+///tip | Dica
+
+Aqui reutilizamos o mesmo modelo do Pydantic.
+
+Mas da mesma forma, nós poderíamos ter validado de alguma outra forma.
+
+///

Good, [USER_REDACTED], you understand the idea. We must think to those that are not so used to English.

Since we are creating this translation, it's good to update the code includes to, so this would be:

{* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *}

here to:

{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2,12:21,24] *}

and here:

{* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *}

Here it is a little strange not translating form feed. But I confess I can't find a good translation to it.

Let's see if anyone can help us, but for now, maybe you can leave the way it is 😄

here to:

{* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *}

here to:

{* ../../docs_src/path_operation_advanced_configuration/tutorial005.py hl[6] *}

maybe you've forgotten to add the "parte" in "também faz parte da..."

the **Ê** is capitalized in "vocÊ"

here to:

{* ../../docs_src/path_operation_advanced_configuration/tutorial006.py hl[19:36,39:40] *}

I'm in doubt here.

I don't know if here we can use the new format for includes... Since the original file is not updated, maybe we can leave the way it is right now

Kept the same way, i am also in doubt

I kept "form feed", i saw the term "alimentação de formulário" being used in automated translations, but it leads to misguiding pages on web search, i didn't found any good translation for this specific term

The purpose of translating is to provide the same content in another language, so it does not make sense to keep untranslated words alongside translated. It is confusing.

I recommend translating it because any science has its own words to describe things proper from that science.

I found other sources on the web using the term "alimentação de formulário", so i will translate this phrase as `um caractere de escape para alimentação de formulário`


🌐 Add Korean translation for `docs/ko/docs/advanced/middlewares.md`

@@ -0,0 +1,96 @@
+# 고급 미들웨어
+
+메인 튜토리얼에서 [[NAME_REDACTED]](../tutorial/middleware.md){.internal-link target=_blank}를 응용프로그램에 추가하는 방법을 읽으셨습니다.
+
+그리고 [CORS with the `CORSMiddleware`](){.internal-link target=_blank}하는 방법도 보셨습니다.
+
+이 섹션에서는 다른 미들웨어들을 사용하는 방법을 알아보겠습니다.
+
+## ASGI 미들웨어 추가하기
+
+**FastAPI**는 Starlette을 기반으로 하고 있으며, ASGI 사양을 구현하므로 ASGI 미들웨어를 사용할 수 있습니다.
+
+미들웨어가 FastAPI나 Starlette용으로 만들어지지 않아도 ASGI 사양을 준수하는 한 동작할 수 있습니다.
+
+일반적으로 ASGI 미들웨어는 첫 번째 인수로 ASGI 앱을 받는 클래스들입니다.
+
+따라서 타사 ASGI 미들웨어 문서에서 일반적으로 다음과 같이 사용하도록 안내할 것입니다.
+
+```Python
+from unicorn import UnicornMiddleware
+
+app = SomeASGIApp()
+
+new_app = UnicornMiddleware(app, some_config="rainbow")
+```
+
+하지만 내부 미들웨어가 서버 오류를 처리하고 사용자 정의 예외 처리기가 제대로 작동하도록 하는 더 간단한 방법을 제공하는 FastAPI(실제로는 Starlette)가 있습니다.
+
+이를 위해 `app.add_middleware()`를 사용합니다(CORS의 예에서와 같이).
+
+```Python
+from fastapi import FastAPI
+from unicorn import UnicornMiddleware
+
+app = FastAPI()
+
+app.add_middleware(UnicornMiddleware, some_config="rainbow")
+```
+
+`app.add_middleware()`는 첫 번째 인수로 미들웨어 클래스와 미들웨어에 전달할 추가 인수를 받습니다.
+
+## 통합 미들웨어
+
+**FastAPI**에는 일반적인 사용 사례를 위한 여러 미들웨어가 포함되어 있으며, 사용 방법은 다음에서 살펴보겠습니다.
+
+/// note | 기술 세부 사항
+
+다음 예제에서는 `from starlette.middleware.something import SomethingMiddleware`를 사용할 수도 있습니다.
+
+**FastAPI**는 개발자의 편의를 위해 `fastapi.middleware`에 여러 미들웨어를 제공합니다. 그러나 사용 가능한 대부분의 미들웨어는 Starlette에서 직접 제공합니다.
+
+///
+
+## `HTTPSRedirectMiddleware`
+
+들어오는 모든 요청이 `https` 또는 `wss`여야 합니다.
+
+`http` 또는 `ws`로 들어오는 모든 요청은 대신 보안 체계로 리디렉션됩니다.
+
+{* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *}
+
+## `TrustedHostMiddleware`
+
+HTTP 호스트 헤더 공격을 방지하기 위해 모든 수신 요청에 올바르게 설정된 `Host` 헤더를 갖도록 강제합니다.
+
+{* ../../docs_src/advanced_middleware/tutorial002.py hl[2,6:8] *}
+
+다음 인수가 지원됩니다:
+
+* `allowed_hosts` - 호스트 이름으로 허용해야 하는 도메인 이름 목록입니다. 일치하는 하위 도메인에 대해 `*.example.com`과 같은 와일드카드 도메인이 지원됩니다. 모든 호스트 이름을 허용하려면 `allowed_hosts=[“*”]`를 사용하거나 미들웨어를 생략하세요.
+
+수신 요청의 유효성이 올바르게 확인되지 않으면 `400`이라는 응답이 전송됩니다.
+
+## `GZipMiddleware`
+
+`Accept-Encoding` 헤더에 `“gzip”`이 포함된 모든 요청에 대해 GZip 응답을 처리합니다.
+
+미들웨어는 표준 응답과 스트리밍 응답을 모두 처리합니다.
+
+{* ../../docs_src/advanced_middleware/tutorial003.py hl[2,6] *}
+
+지원되는 인수는 다음과 같습니다:
+
+* `minimum_size` - 이 최소 크기(바이트)보다 작은 응답은 GZip하지 않습니다. 기본값은 `500`입니다.
+* `compresslevel` - GZip 압축 중에 사용됩니다. 1에서 9 사이의 정수입니다. 기본값은 `9`입니다. 값이 낮을수록 압축 속도는 빨라지지만 파일 크기는 커지고, 값이 높을수록 압축 속도는 느려지지만 파일 크기는 작아집니다.
+
+## 기타 미들웨어
+
+다른 많은 ASGI 미들웨어가 있습니다.
+
+예를 들어:
+
+유비콘의 `ProxyHeadersMiddleware`>
+MessagePack
+
+사용 가능한 다른 미들웨어를 확인하려면 스타렛의 미들웨어 문서 및 ASGI [NAME_REDACTED]를 참조하세요.

리뷰 참고 부탁드립니다!

LGTM !

```suggestion
/// note | “기술 세부 사항”
```
참고 제외하는 게 좋을 거 같습니다!


🌐 Add Korean translation for `docs/ko/docs/advanced/openapi-webhooks.md`

@@ -0,0 +1,55 @@
+# OpenAPI 웹훅(Webhooks)
+
+API **사용자**에게 특정 **이벤트**가 발생할 때 *그들*의 앱(시스템)에 요청을 보내 **알림**을 전달할 수 있다는 것을 알리고 싶은 경우가 있습니다.
+
+즉, 일반적으로 사용자가 API에 요청을 보내는 것과는 반대로, **API**(또는 앱)가 **사용자의 시스템**(그들의 API나 앱)으로 **요청을 보내는** 상황을 의미합니다.
+
+이를 흔히 **웹훅(Webhook)**이라고 부릅니다.
+
+## 웹훅 스텝
+
+**코드에서** 웹훅으로 보낼 메시지, 즉 요청의 **바디(body)**를 정의하는 것이 일반적인 프로세스입니다.
+
+앱에서 해당 요청이나 이벤트를 전송할 **시점**을 정의합니다.
+
+**사용자**는 앱이 해당 요청을 보낼 **URL**을 정의합니다. (예: 웹 대시보드에서 설정)
+
+웹훅의 URL을 등록하는 방법과 이러한 요청을 실제로 전송하는 코드에 대한 모든 로직은 여러분에게 달려 있습니다. 원하는대로 **고유의 코드**를 작성하면 됩니다.
+
+## **FastAPI**와 OpenAPI로 웹훅 문서화하기
+
+**FastAPI**를 사용하여 OpenAPI와 함께 웹훅의 이름, 앱이 보낼 수 있는 HTTP 작업 유형(예: `POST`, `PUT` 등), 그리고 보낼 요청의 **바디**를 정의할 수 있습니다.
+
+이를 통해 사용자가 **웹훅** 요청을 수신할 **API 구현**을 훨씬 쉽게 할 수 있으며, 경우에 따라 사용자 API 코드의 일부를 자동 생성할 수도 있습니다.
+
+/// info
+
+웹훅은 OpenAPI 3.1.0 이상에서 지원되며, FastAPI `0.99.0` 이상 버전에서 사용할 수 있습니다.
+
+///
+
+## 웹훅이 포함된 앱 만들기
+
+**FastAPI** 애플리케이션을 만들 때, `webhooks` 속성을 사용하여 *웹훅*을 정의할 수 있습니다. 이는 `[USER_REDACTED].webhooks.post()`와 같은 방식으로 *경로(path) 작업*을 정의하는 것과 비슷합니다.
+
+{* ../../docs_src/openapi_webhooks/tutorial001.py hl[9:13,36:53] *}
+
+이렇게 정의한 웹훅은 **OpenAPI** 스키마와 자동 **문서화 UI**에 표시됩니다.
+
+/// info
+
+`app.webhooks` 객체는 사실 `APIRouter`일 뿐이며, 여러 파일로 앱을 구성할 때 사용하는 것과 동일한 타입입니다.
+
+///
+
+웹훅에서는 실제 **경로(path)** (예: `/items/`)를 선언하지 않는 점에 유의해야 합니다. 여기서 전달하는 텍스트는 **식별자**로, 웹훅의 이름(이벤트 이름)입니다. 예를 들어, `[USER_REDACTED].webhooks.post("new-subscription")`에서 웹훅 이름은 `new-subscription`입니다.
+
+이는 실제 **URL 경로**는 **사용자**가 다른 방법(예: 웹 대시보드)을 통해 지정하도록 기대되기 때문입니다.
+
+### 문서 확인하기
+
+이제 앱을 시작하고 http://127.0.0.1:8000/docs로 이동해 봅시다.
+
+문서에서 기존 *경로 작업*뿐만 아니라 **웹훅**도 표시된 것을 확인할 수 있습니다:
+
+

리뷰 내용 참고하시면 좋을 거 같습니다!

LGTM 😀

```suggestion
이를 흔히 **웹훅(Webhook)**이라고 부릅니다.
```
이것을 > 이를 수정하는 게 좀 더 매끄러울 것 같습니다!

```suggestion
웹훅의 URL을 등록하는 방법과 이러한 요청을 실제로 전송하는 코드에 대한 모든 로직은 여러분에게 달려 있습니다. 원하는대로 **고유의 코드**를 작성하면 됩니다.
```
사용자 > 여러분 이 부분에서 서비스를 제공하는 측을 의미하는 거 같아서 확인 부탁드립니다!

```suggestion
웹훅에서는 실제 **경로(path)** (예: `/items/`)를 선언하지 않는 점에 유의해야 합니다. 여기서 전달하는 텍스트는 **식별자**로, 웹훅의 이름(이벤트 이름)입니다. 예를 들어, `[USER_REDACTED].webhooks.post("new-subscription")`에서 웹훅 이름은 `new-subscription`입니다.
```
주의하세요. > 유의해야 합니다.  합니다 체로 변경이 좋을 거 같습니다!

```suggestion
이제 앱을 시작하고 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>로 이동해 봅시다.
```
보세요. > 봅시다.  합니다 체로 변경이 좋을 거 같습니다!

LGTM!


🌐 Add Korean translation for `docs/ko/docs/security/index.md`

Add Korean translation for docs/ko/docs/security/index.md

https://github.com/fastapi/fastapi/issues/2017

@@ -0,0 +1,19 @@
+# 고급 보안
+
+## 추가 기능
+
+[자습서 - 사용자 가이드: 보안](../../tutorial/security/index.md){.internal-link target=_blank} 문서에서 다룬 내용 외에도 보안 처리를 위한 몇 가지 추가 기능이 있습니다.
+
+/// tip
+
+다음 섹션은 **반드시 "고급"** 기능은 아닙니다.
+
+그리고 여러분의 사용 사례에 따라, 적합한 해결책이 그 중 하나에 있을 가능성이 있습니다.
+
+///
+
+## 먼저 자습서 읽기
+
+다음 섹션은 이미 [자습서 - 사용자 가이드: 보안](../../tutorial/security/index.md){.internal-link target=_blank} 문서를 읽었다고 가정합니다.
+
+이 섹션들은 모두 동일한 개념을 바탕으로 하며, 추가 기능을 제공합니다.

검토해서 생각해봐 주시면 감사하겠습니다

LGTM🚀

'그리고 여러분의 사용 사례에 따라, 적합한 해결책이 그 중 하나에 있을 가능성이 있습니다.'로 바꾸면 이해하기 쉬울 것 같습니다.

'[자습서 - 사용자 가이드: 보안](../../tutorial/security/index.md){.internal-link target=_blank} 문서에서 다룬 내용 외에도 보안 처리를 위한 몇 가지 추가 기능이 있습니다.'가 한국어로 했을 때 더 어울릴 것 같습니다.

리뷰 감사합니다!

리뷰 감사합니다!


🌐 Add Korean translation for `ko/docs/advanced/response-headers.md`

@@ -0,0 +1,45 @@
+# 응답 헤더
+
+## `Response` 매개변수 사용하기
+
+여러분은 *경로 작동 함수*에서 `Response` 타입의 매개변수를 선언할 수 있습니다 (쿠키와 같이 사용할 수 있습니다).
+
+그런 다음, 여러분은 해당 *임시* 응답 객체에서 헤더를 설정할 수 있습니다.
+
+```Python hl_lines="1  7-8"
+{!../../docs_src/response_headers/tutorial002.py!}
+```
+
+그 후, 일반적으로 사용하듯이 필요한 객체(`dict`, 데이터베이스 모델 등)를 반환할 수 있습니다.
+
+`response_model`을 선언한 경우, 반환한 객체를 필터링하고 변환하는 데 여전히 사용됩니다.
+
+**FastAPI**는 해당 *임시* 응답에서 헤더(쿠키와 상태 코드도 포함)를 추출하여, 여러분이 반환한 값을 포함하는 최종 응답에 `response_model`로 필터링된 값을 넣습니다.
+
+또한, 종속성에서 `Response` 매개변수를 선언하고 그 안에서 헤더(및 쿠키)를 설정할 수 있습니다.
+
+## `Response` 직접 반환하기
+
+`Response`를 직접 반환할 때에도 헤더를 추가할 수 있습니다.
+
+[응답을 직접 반환하기](response-directly.md){.internal-link target=_blank}에서 설명한 대로 응답을 생성하고, 헤더를 추가 매개변수로 전달하세요.
+
+```Python hl_lines="10-12"
+{!../../docs_src/response_headers/tutorial001.py!}
+```
+
+/// note | "기술적 세부사항"
+
+`from starlette.responses import Response`나 `from starlette.responses import JSONResponse`를 사용할 수도 있습니다.
+
+**FastAPI**는 `starlette.responses`를 `fastapi.responses`로 개발자의 편의를 위해 직접 제공하지만, 대부분의 응답은 Starlette에서 직접 제공됩니다.
+
+그리고 `Response`는 헤더와 쿠키를 설정하는 데 자주 사용될 수 있으므로, **FastAPI**는 `fastapi.Response`로도 이를 제공합니다.
+
+///
+
+## 커스텀 헤더
+
+‘X-’ 접두어를 사용하여 커스텀 사설 헤더를 추가할 수 있습니다.
+
+하지만, 여러분이 브라우저에서 클라이언트가 볼 수 있기를 원하는 커스텀 헤더가 있는 경우, CORS 설정에 이를 추가해야 합니다([CORS ([NAME_REDACTED])](../tutorial/cors.md){.internal-link target=_blank}에서 자세히 알아보세요). `expose_headers` 매개변수를 사용하여 Starlette의 CORS 설명서에 문서화된 대로 설정할 수 있습니다.

LGTM

LGTM !

```suggestion
[응답을 직접 반환하기](response-directly.md){.internal-link target=_blank}에서 설명한 대로 응답을 생성하고, 헤더를 추가 매개변수로 전달하세요.
```
'Return a [NAME_REDACTED] we change this part to '응답을 직접 반환하기' the translation might look clearer

Thank you for your review!


🌐 Add Korean translation for `docs/ko/docs/advanced/testing-websockets.md`

Add Korean translation for docs/ko/docs/advanced/testing-websockets.md

@@ -0,0 +1,15 @@
+# WebSocket 테스트하기
+
+`TestClient`를 사용하여 WebSocket을 테스트할 수 있습니다.
+
+이를 위해 `with` 문에서 `TestClient`를 사용하여 WebSocket에 연결합니다:
+
+```Python hl_lines="27-31"
+{!../../docs_src/app_testing/tutorial002.py!}
+```
+
+/// note | 참고
+
+자세한 내용은 Starlette의  WebSocket 테스트에 관한 설명서를 참고하시길 바랍니다.
+
+///

LGTM !

LGTM👍

```suggestion
자세한 내용은 Starlette의 <a href="https://www.starlette.io/testclient/#testing-websocket-sessions" class="external-link" target="_blank"> WebSocket 테스트</a>에 관한 설명서를 참고하세요.
```

How about modifying this part like this?


🌐 Add Korean translation for `docs/ko/docs/advanced/using_request_directly.md`

Add Korean translation for docs/ko/docs/advanced/using_request_directly.md

@@ -0,0 +1,58 @@
+# `Request` 직접 사용하기
+
+지금까지 요청에서 필요한 부분을 각 타입으로 선언하여 사용해 왔습니다.
+
+다음과 같은 곳에서 데이터를 가져왔습니다:
+
+* 경로의 파라미터로부터.
+* 헤더.
+* 쿠키.
+* 기타 등등.
+
+이렇게 함으로써, **FastAPI**는 데이터를 검증하고 변환하며, API에 대한 문서를 자동화로 생성합니다.
+
+하지만 `Request` 객체에 직접 접근해야 하는 상황이 있을 수 있습니다.
+
+## `Request` 객체에 대한 세부 사항
+
+**FastAPI**는 실제로 내부에 **Starlette**을 사용하며, 그 위에 여러 도구를 덧붙인 구조입니다. 따라서 여러분이 필요할 때 Starlette의 `Request` 객체를 직접 사용할 수 있습니다.
+
+`Request` 객체에서 데이터를 직접 가져오는 경우(예: 본문을 읽기)에는 FastAPI가 해당 데이터를 검증하거나 변환하지 않으며, 문서화(OpenAPI를 통한 문서 자동화(로 생성된) API 사용자 인터페이스)도 되지 않습니다.
+
+그러나 다른 매개변수(예: Pydantic 모델을 사용한 본문)는 여전히 검증, 변환, 주석 추가 등이 이루어집니다.
+
+하지만 특정한 경우에는 `Request` 객체에 직접 접근하는 것이 유용할 수 있습니다.
+
+## `Request` 객체를 직접 사용하기
+
+여러분이 클라이언트의 IP 주소/호스트 정보를 *경로 작동 함수* 내부에서 가져와야 한다고 가정해 보겠습니다.
+
+이를 위해서는 요청에 직접 접근해야 합니다.
+
+```Python hl_lines="1  7-8"
+{!../../docs_src/using_request_directly/tutorial001.py!}
+```
+
+*경로 작동 함수* 매개변수를 `Request` 타입으로 선언하면 **FastAPI**가 해당 매개변수에 `Request` 객체를 전달하는 것을 알게 됩니다.
+
+/// tip | 팁
+
+이 경우, 요청 매개변수와 함께 경로 매개변수를 선언한 것을 볼 수 있습니다.
+
+따라서, 경로 매개변수는 추출되고 검증되며 지정된 타입으로 변환되고 OpenAPI로 주석이 추가됩니다.
+
+이와 같은 방식으로, 다른 매개변수들을 평소처럼 선언하면서, 부가적으로 `Request`도 가져올 수 있습니다.
+
+///
+
+## `Request` 설명서
+
+여러분은 `Request` 객체에 대한 더 자세한 내용을 공식 Starlette 설명서 사이트에서 읽어볼 수 있습니다.
+
+/// note | 기술 세부사항
+
+`from starlette.requests import Request`를 사용할 수도 있습니다.
+
+**FastAPI**는 여러분(개발자)를 위한 편의를 위해 이를 직접 제공하지만, 실제로는 Starlette에서 가져온 것입니다.
+
+///

의견 검토해 주시면 감사하겠습니다.

LGTM🔥

'옆에'보다 '~와 함께'가 이해하기 쉬울 것 같습니다

의견 반영하여 수정하였습니다. 감사합니다!!

![스크린샷 2024-11-05 115613](https://github.com/[USER_REDACTED]nts/assets/d8d0881d-4140-4c60-9e21-1b01c581982f)
![스크린샷 2024-11-05 115547](https://github.com/[USER_REDACTED]nts/assets/6660f343-2c86-4ff7-b049-c751ffdce08c)

영문문서와 다르게 표시되어 보이는 것 같아서 한 번 찾아보겠습니다

merge 되면 제대로 보일지 원리를 잘 모르겠어서

note | "[NAME_REDACTED]"
혹시 그 부분을 | 를 이용해서 컨벤션을 맞춰보실 수 있으신가요?

말씀해주셔서 감사합니다. 말씀 주신 대로 수정하였습니다!


🌐 Add Korean translation for `docs/ko/docs/how-to/conditional-openapi.md`

@@ -0,0 +1,61 @@
+# 조건부적인 OpenAPI
+
+필요한 경우, 설정 및 환경 변수를 사용하여 환경에 따라 조건부로 OpenAPI를 구성하고 완전히 비활성화할 수도 있습니다.
+
+## 보안, API 및 docs에 대해서
+
+프로덕션에서, 문서화된 사용자 인터페이스(UI)를 숨기는 것이 API를 보호하는 방법이 *되어서는 안 됩니다*.
+
+이는 API에 추가적인 보안을 제공하지 않으며, *경로 작업*은 여전히 동일한 위치에서 사용 할 수 있습니다.
+
+코드에 보안 결함이 있다면, 그 결함은 여전히 존재할 것입니다.
+
+문서를 숨기는 것은 API와 상호작용하는 방법을 이해하기 어렵게 만들며, 프로덕션에서 디버깅을 더 어렵게 만들 수 있습니다. 이는 단순히 '모호성에 의한 보안'의 한 형태로 간주될 수 있습니다.
+
+API를 보호하고 싶다면, 예를 들어 다음과 같은 더 나은 방법들이 있습니다:
+
+* 요청 본문과 응답에 대해 잘 정의된 Pydantic 모델을 사용하도록 하세요.
+
+* 종속성을 사용하여 필요한 권한과 역할을 구성하세요.
+
+* 평문 비밀번호를 절대 저장하지 말고, 오직 암호화된 비밀번호만 저장하세요.
+
+* Passlib과 JWT 토큰과 같은 잘 알려진 암호화 도구들을 구현하고 사용하세요.
+
+* 필요한 곳에 OAuth2 범위를 사용하여 더 세분화된 권한 제어를 추가하세요.
+
+* 등등....
+
+그럼에도 불구하고, 특정 환경(예: 프로덕션)에서 또는 환경 변수의 설정에 따라 API 문서를 비활성화해야 하는 매우 특정한 사용 사례가 있을 수 있습니다.
+
+## 설정 및 환경변수의 조건부 OpenAPI
+
+동일한 Pydantic 설정을 사용하여 생성된 OpenAPI 및 문서 UI를 쉽게 구성할 수 있습니다.
+
+예를 들어:
+
+{* ../../docs_src/conditional_openapi/tutorial001.py hl[6,11] *}
+
+여기서 `openapi_url` 설정을 기본값인 `"/openapi.json"`으로 선언합니다.
+
+그런 뒤, 우리는 `FastAPI` 앱을 만들 때 그것을 사용합니다.
+
+환경 변수 `OPENAPI_URL`을 빈 문자열로 설정하여 OpenAPI(문서 UI 포함)를 비활성화할 수도 있습니다. 예를 들어:
+
+

+
+```console
+$ OPENAPI_URL= uvicorn main:app
+
+<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+

+
+그리고 `/openapi.json`, `/docs` 또는 `/redoc`의 URL로 이동하면 `404 Not Found`라는 오류가 다음과 같이 표시됩니다:
+
+```JSON
+{
+    "detail": "Not Found"
+}
+```

Great job! Only one thing left to do.

LGTM 🚀

```suggestion
이는 API에 추가적인 보안을 제공하지 않으며, *경로 작업*은 여전히 동일한 위치에서 사용 할 수 있습니다.
```
"그것은" is not natural.

원문에도 "Then", "And then" 이런 식으로 되어 있긴 하지만..
"그런 다음"이 너무 반복되어서 조금 어색합니다. 가능하다면 접속사를 조금 다듬었으면 좋겠습니다.

리뷰 감사합니다!

```suggestion
* 요청 본문과 응답에 대해 잘 정의된 Pydantic 모델을 사용하도록 하세요.
```
Untranslated "request body" and "response"


🌐 Add Korean translation for `docs/ko/docs/advanced/templates.md`

Add Korean translation for docs/ko/docs/advanced/templates.md

@@ -0,0 +1,127 @@
+# 템플릿
+
+**FastAPI**와 함께 원하는 어떤 템플릿 엔진도 사용할 수 있습니다.
+
+일반적인 선택은 Jinja2로, Flask와 다른 도구에서도 사용됩니다.
+
+설정을 쉽게 할 수 있는 유틸리티가 있으며, 이를 **FastAPI** 애플리케이션에서 직접 사용할 수 있습니다(Starlette 제공).
+
+## 의존성 설치
+
+가상 환경을 생성하고(virtual environment{.internal-link target=_blank}), 활성화한 후 jinja2를 설치해야 합니다:
+
+
+

+
+```console
+$ pip install jinja2
+
+---> 100%
+```
+
+

+
+## 사용하기 `Jinja2Templates`
+
+* `Jinja2Templates`를 가져옵니다.
+* 나중에 재사용할 수 있는 `templates` 객체를 생성합니다.
+* 템플릿을 반환할 경로 작업에 `Request` 매개변수를 선언합니다.
+* 생성한 `templates`를 사용하여 `TemplateResponse`를 렌더링하고 반환합니다. 템플릿의 이름, 요청 객체 및 Jinja2 템플릿 내에서 사용될 키-값 쌍이 포함된 "컨텍스트" 딕셔너리도 전달합니다.
+
+
+```Python hl_lines="4  11  15-18"
+{!../../docs_src/templates/tutorial001.py!}
+```
+
+/// note | 참고
+
+FastAPI 0.108.0 이전과 Starlette 0.29.0에서는 `name`이 첫 번째 매개변수였습니다.
+
+또한 이전 버전에서는 `request` 객체가 Jinja2의 컨텍스트에서 키-값 쌍의 일부로 전달되었습니다.
+
+///
+
+/// tip | 팁
+
+`response_class=HTMLResponse`를 선언하면 문서 UI 응답이 HTML임을 알 수 있습니다.
+
+///
+
+/// note | 기술 세부 사항
+`from starlette.templating import Jinja2Templates`를 사용할 수도 있습니다.
+
+**FastAPI**는 개발자를 위한 편리함으로 `fastapi.templating` 대신 `starlette.templating`을 제공합니다. 하지만 대부분의 사용 가능한 응답은 Starlette에서 직접 옵니다. `Request` 및 `StaticFiles`도 마찬가지입니다.
+///
+
+## 템플릿 작성하기
+
+그런 다음 `templates/item.html`에 템플릿을 작성할 수 있습니다. 예를 들면:
+
+```jinja hl_lines="7"
+{!../../docs_src/templates/templates/item.html!}
+```
+
+### 템플릿 컨텍스트 값
+
+다음과 같은 HTML에서:
+
+{% raw %}
+
+```jinja
+Item ID: {{ id }}
+```
+
+{% endraw %}
+
+...이는 전달한 "컨텍스트" `dict`에서 가져온 `id`를 표시합니다:
+
+```Python
+{"id": id}
+```
+
+예를 들어, ID가 `42`일 경우, 이는 다음과 같이 렌더링됩니다:
+
+```html
+Item ID: 42
+```
+
+### 템플릿 `url_for` 인수
+
+템플릿 내에서 `url_for()`를 사용할 수도 있으며, 이는 *경로 작업 함수*에서 사용될 인수와 동일한 인수를 받습니다.
+
+따라서 다음과 같은 부분에서:
+
+{% raw %}
+
+```jinja
+<a href="{{ url_for('read_item', id=id) }}">
+```
+
+{% endraw %}
+
+...이는 *경로 작업 함수* `read_item(id=id)`가 처리할 동일한 URL로 링크를 생성합니다.
+
+예를 들어, ID가 `42`일 경우, 이는 다음과 같이 렌더링됩니다:
+```html
+<a href="/items/42">
+```
+
+## 템플릿과 정적 파일
+
+템플릿 내에서 `url_for()`를 사용할 수 있으며, 예를 들어 `name="static"`으로 마운트한 `StaticFiles`와 함께 사용할 수 있습니다.
+
+```jinja hl_lines="4"
+{!../../docs_src/templates/templates/item.html!}
+```
+
+이 예제에서는 `static/styles.css`에 있는 CSS 파일에 연결될 것입니다:
+
+```CSS hl_lines="4"
+{!../../docs_src/templates/static/styles.css!}
+```
+
+그리고 `StaticFiles`를 사용하고 있으므로, 해당 CSS 파일은 **FastAPI** 애플리케이션에서 `/static/styles.css` URL로 자동 제공됩니다.
+
+## 더 많은 세부 사항
+
+템플릿 테스트를 포함한 더 많은 세부 사항은 Starlette의 템플릿 문서를 확인하세요.

LGTM!

It's broken. See [Translation specific tips and guidelines](https://fastapi.tiangolo.com/contributing/#translation-specific-tips-and-guidelines) and https://github.com/fastapi/fastapi/discussions/3167#discussioncomment-721448

> In lines starting with `///` translate only the text part after `|`. Leave the rest unchanged.

```suggestion
가상 환경을 생성하고(virtual environment{.internal-link target=_blank}), 활성화한 후 jinja2를 설치해야 합니다:
```
markdown has broken.
please check your work with generated docs by [NAME_REDACTED]

```suggestion
* 생성한 `templates`를 사용하여 `TemplateResponse`를 렌더링하고 반환합니다. 템플릿의 이름, 요청 객체 및 Jinja2 템플릿 내에서 사용될 키-값 쌍이 포함된 "컨텍스트" 딕셔너리도 전달합니다.
```

```suggestion
///

/// tip | 참고

`response_class=HTMLResponse`를 선언하면 문서 UI 응답이 HTML임을 알 수 있습니다.

///

/// 노트 | "기술 세부 사항"
`from starlette.templating import Jinja2Templates`를 사용할 수도 있습니다.

**FastAPI**는 개발자를 위한 편리함으로 `fastapi.templating` 대신 `starlette.templating`을 제공합니다. 하지만 대부분의 사용 가능한 응답은 Starlette에서 직접 옵니다. `Request` 및 `StaticFiles`도 마찬가지입니다.
///
```
you need to your generated docs (2)

```suggestion
그런 다음 `templates/item.html`에 템플릿을 작성할 수 있습니다. 예를 들면:
```

LGTM!

thank you!

```suggestion
/// note | 참고
```

```suggestion
/// tip | 팁
```

```suggestion
/// note | "기술 세부 사항"
```

감사합니다


🌐 Add Korean translation to `docs/ko/docs/advanced/additional-status-codes.md`

@@ -0,0 +1,41 @@
+# 추가 상태 코드
+
+기본적으로 **FastAPI**는 응답을 `JSONResponse`를 사용하여 반환하며, *경로 작업(path operation)*에서 반환한 내용을 해당 `JSONResponse` 안에 넣어 반환합니다.
+
+기본 상태 코드 또는 *경로 작업*에서 설정한 상태 코드를 사용합니다.
+
+## 추가 상태 코드
+
+기본 상태 코드와 별도로 추가 상태 코드를 반환하려면 `JSONResponse`와 같이 `Response`를 직접 반환하고 추가 상태 코드를 직접 설정할 수 있습니다.
+
+예를 들어 항목을 업데이트할 수 있는 *경로 작업*이 있고 성공 시 200 “OK”의 HTTP 상태 코드를 반환한다고 가정해 보겠습니다.
+
+하지만 새로운 항목을 허용하기를 원할 것입니다. 항목이 이전에 존재하지 않았다면 이를 생성하고 HTTP 상태 코드 201 "Created"를 반환합니다.
+
+이를 위해서는 `JSONResponse`를 가져와서 원하는 `status_code`를 설정하여 콘텐츠를 직접 반환합니다:
+
+{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *}
+
+/// warning | 경고
+
+위의 예제처럼 `Response`를 직접 반환하면 바로 반환됩니다.
+
+모델 등과 함께 직렬화되지 않습니다.
+
+원하는 데이터가 있는지, 값이 유효한 JSON인지 확인합니다(`JSONResponse`를 사용하는 경우).
+
+///
+
+/// note | 기술적 세부 정보
+
+`from starlette.responses import JSONResponse`를 사용할 수도 있습니다.
+
+**FastAPI**는 개발자 여러분을 위한 편의성으로 `fastapi.responses`와 동일한 `starlette.responses`를 제공합니다. 그러나 사용 가능한 응답의 대부분은 Starlette에서 직접 제공됩니다. `status` 또한 마찬가지입니다.
+
+///
+
+## OpenAPI 및 API 문서
+
+추가 상태 코드와 응답을 직접 반환하는 경우, FastAPI는 반환할 내용을 미리 알 수 있는 방법이 없기 때문에 OpenAPI 스키마(API 문서)에 포함되지 않습니다.
+
+하지만 다음을 사용하여 코드에 이를 문서화할 수 있습니다: [추가 응답](additional-responses.md){.internal-link target=_blank}.

리뷰 참고바랍니다!

LGTM !

LGTM!👍

Use `경로 작업` or `경로 작동` instead of `경로 연산` Ref: https://github.com/fastapi/fastapi/discussions/3167#discussioncomment-721448

Also, if possible, make it a more natural sentence. I think "`JSONResponse`에 넣어 `JSONResponse`를 사용하여" is unnatural.

```suggestion
/// warning | "경고"
```

It's broken.

```suggestion
/// note 참고 | "기술적 세부 정보"
```

```suggestion
**FastAPI**는 개발자의 편의를 위해 `fastapi.responses`와 동일한 `starlette.responses`를 제공합니다. 하지만 사용 가능한 대부분의 응답은 Starlette에서 직접 제공합니다. 상태도 마찬가지입니다.
```

`additional-responses.md` refers to a filename; the original title is "[NAME_REDACTED] in OpenAPI"

<img width="740" alt="image" src="https://github.com/[USER_REDACTED]nts/assets/9a91ee44-363a-47f2-9914-3ce14d777bfd">
It's broken

```suggestion
/// note | "기술적 세부 정보"
```
It will fix it

```suggestion
원하는 데이터가 있는지, 값이 유효한 JSON인지 확인합니다(`JSONResponse`를 사용하는 경우).
```
확인하세요 > 확인합니다 뒤가 더 읽기 편할 거 같습니다


🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request-files.md`

@@ -0,0 +1,176 @@
+# Arquivos de Requisição
+
+Você pode definir arquivos para serem enviados pelo cliente usando `File`.
+
+/// info | Informação
+
+Para receber arquivos enviados, primeiro instale o `python-multipart`.
+
+Garanta que você criou um [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, o ativou e então o instalou, por exemplo:
+
+```console
+$ pip install python-multipart
+```
+
+Isso é necessário, visto que os arquivos enviados são enviados como "dados de formulário".
+
+///
+
+## Importe `File`
+
+Importe `File` e `UploadFile` de `fastapi`:
+
+{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
+
+## Definir Parâmetros `File`
+
+Crie parâmetros de arquivo da mesma forma que você faria para `Body` ou `Form`:
+
+{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *}
+
+/// info | Informação
+
+`File` é uma classe que herda diretamente de `Form`.
+
+Mas lembre-se que quando você importa `Query`, `Path`, `File` e outros de `fastapi`, eles são, na verdade, funções que retornam classes especiais.
+
+///
+
+/// tip | Dica
+
+Para declarar corpos de arquivos, você precisa usar `File`, caso contrário, os parâmetros seriam interpretados como parâmetros de consulta ou parâmetros de corpo (JSON).
+
+///
+
+Os arquivos serão enviados como "dados de formulário".
+
+Se você declarar o tipo do parâmetro da função da sua *operação de rota* como `bytes`, o **FastAPI** lerá o arquivo para você e você receberá o conteúdo como `bytes`.
+
+Mantenha em mente que isso significa que todo o conteúdo será armazenado na memória. Isso funcionará bem para arquivos pequenos.
+
+Mas há muitos casos em que você pode se beneficiar do uso de `UploadFile`.
+
+## Parâmetros de Arquivo com `UploadFile`
+
+Defina um parâmetro de arquivo com um tipo de `UploadFile`:
+
+{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *}
+
+Utilizar `UploadFile` tem várias vantagens sobre `bytes`:
+
+* Você não precisa utilizar o `File()` no valor padrão do parâmetro.
+* Ele utiliza um arquivo "spooled":
+    * Um arquivo armazenado na memória até um limite máximo de tamanho, e após passar esse limite, ele será armazenado no disco.
+* Isso significa que funcionará bem para arquivos grandes como imagens, vídeos, binários grandes, etc., sem consumir toda a memória.
+* Você pode receber metadados do arquivo enviado.
+* Ele tem uma file-like interface `assíncrona`.
+* Ele expõe um objeto python `SpooledTemporaryFile` que você pode passar diretamente para outras bibliotecas que esperam um objeto semelhante a um arquivo("file-like").
+
+### `UploadFile`
+
+`UploadFile` tem os seguintes atributos:
+
+* `filename`: Uma `str` com o nome do arquivo original que foi enviado (por exemplo, `myimage.jpg`).
+* `content_type`: Uma `str` com o tipo de conteúdo (tipo MIME / tipo de mídia) (por exemplo, `image/jpeg`).
+* `file`: Um `SpooledTemporaryFile` (um file-like objeto). Este é o objeto de arquivo Python que você pode passar diretamente para outras funções ou bibliotecas que esperam um objeto semelhante a um arquivo("file-like").
+
+`UploadFile` tem os seguintes métodos `assíncronos`. Todos eles chamam os métodos de arquivo correspondentes por baixo dos panos (usando o `SpooledTemporaryFile` interno).
+
+* `write(data)`: Escreve `data` (`str` ou `bytes`) no arquivo.
+* `read(size)`: Lê `size` (`int`) bytes/caracteres do arquivo.
+* `seek(offset)`: Vai para o byte na posição `offset` (`int`) no arquivo.
+    * Por exemplo, `await myfile.seek(0)` irá para o início do arquivo.
+    * Isso é especialmente útil se você executar `await myfile.read()` uma vez e precisar ler o conteúdo novamente.
+* `close()`: Fecha o arquivo.
+
+Como todos esses métodos são métodos `assíncronos`, você precisa "aguardar" por eles.
+
+Por exemplo, dentro de uma função de *operação de rota* `assíncrona`, você pode obter o conteúdo com:
+
+```Python
+contents = await myfile.read()
+```
+
+Se você estiver dentro de uma função de *operação de rota* normal `def`, você pode acessar o `UploadFile.file` diretamente, por exemplo:
+
+```Python
+contents = myfile.file.read()
+```
+
+/// note | Detalhes Técnicos do `async`
+
+Quando você usa os métodos `async`, o **FastAPI** executa os métodos de arquivo em um threadpool e aguarda por eles.
+
+///
+
+/// note | "Detalhes Técnicos do Starlette"
+
+O `UploadFile` do ***FastAPI** herda diretamente do `UploadFile` do **Starlette** , mas adiciona algumas partes necessárias para torná-lo compatível com o **Pydantic** e as outras partes do FastAPI.
+
+///
+
+## O que é "[NAME_REDACTED]"
+
+O jeito que os formulários HTML (`<form></form>`) enviam os dados para o servidor normalmente usa uma codificação "especial" para esses dados, a qual é diferente do JSON.
+
+**FastAPI** se certificará de ler esses dados do lugar certo, ao invés de JSON.
+
+/// note | "Detalhes Técnicos"
+
+Dados de formulários normalmente são codificados usando o "media type" (tipo de mídia) `application/x-www-form-urlencoded` quando não incluem arquivos.
+
+Mas quando o formulário inclui arquivos, ele é codificado como `multipart/form-data`. Se você usar `File`, o **FastAPI** saberá que tem que pegar os arquivos da parte correta do corpo da requisição.
+
+Se você quiser ler mais sobre essas codificações e campos de formulário, vá para a MDN web docs para POST.
+
+///
+
+/// warning | Aviso
+
+Você pode declarar múltiplos parâmetros `File` e `Form` em uma *operação de rota*, mas você não pode declarar campos `Body` que você espera receber como JSON, pois a requisição terá o corpo codificado usando `multipart/form-data` ao invés de `application/json`.
+
+Isso não é uma limitação do **FastAPI**, é parte do protocolo HTTP.
+
+///
+
+## Upload de [NAME_REDACTED]
+
+Você pode tornar um arquivo opcional usando anotações de tipo padrão e definindo um valor padrão de `None`:
+
+{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *}
+
+## `UploadFile` com [NAME_REDACTED]
+
+Você também pode usar `File()` com `UploadFile`, por exemplo, para definir metadados adicionais:
+
+{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}
+
+## Uploads de Múltiplos Arquivos
+
+É possível realizar o upload de vários arquivos ao mesmo tempo.
+
+Eles serão associados ao mesmo "campo de formulário" enviado usando "dados de formulário".
+
+Para usar isso, declare uma lista de `bytes` ou `UploadFile`:
+
+{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *}
+
+Você receberá, tal como declarado, uma `list` de `bytes` ou `UploadFile`.
+
+/// note | "Detalhes Técnicos"
+
+Você pode também pode usar `from starlette.responses import HTMLResponse`.
+
+**FastAPI** providencia o mesmo `starlette.responses` que `fastapi.responses` apenas como uma conveniência para você, o desenvolvedor. Mas a maioria das respostas disponíveis vem diretamente do Starlette.
+
+///
+
+### Uploads de Múltiplos Arquivos com [NAME_REDACTED]
+
+Da mesma forma de antes, você pode usar `File()` para definir parâmetros adicionais, mesmo para `UploadFile`:
+
+{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *}
+
+## Recapitulando
+
+Utilize `File`, `bytes` e `UploadFile` para declarar arquivos a serem enviados na requisição, enviados como dados de formulário.

Great, 🚀.

Great [USER_REDACTED] ✨

Thank you ❤

Just missing some highlights

See this issue: https://github.com/fastapi/fastapi/issues/12554

You can replace these blocks with:

```Python hl_lines="3"
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
```

The same here: Update docs include syntax for source examples https://github.com/fastapi/fastapi/issues/12554

just missed the accent here: *m**ú**ltiplos*

Ok, I'll take a look, and commit the changes. Thank you

missed the highlight of the line 9:

{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *}

here to:

{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}

here to:

{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *}

Ohh sorry, I got a little confused. I just fixed it!


🌐 Add Portuguese translation for `docs/pt/docs/advanced/openapi-callbacks.md`

@@ -0,0 +1,194 @@
+# Callbacks na OpenAPI
+
+Você poderia criar uma API com uma *operação de rota* que poderia acionar uma solicitação a uma *API externa* criada por outra pessoa (provavelmente o mesmo desenvolvedor que estaria *usando* sua API).
+
+O processo que acontece quando seu aplicativo de API chama a *API externa* é chamado de "callback". Porque o software que o desenvolvedor externo escreveu envia uma solicitação para sua API e então sua API *chama de volta*, enviando uma solicitação para uma *API externa* (que provavelmente foi criada pelo mesmo desenvolvedor).
+
+Nesse caso, você poderia querer documentar como essa API externa *deveria* ser. Que *operação de rota* ela deveria ter, que corpo ela deveria esperar, que resposta ela deveria retornar, etc.
+
+## Um aplicativo com callbacks
+
+Vamos ver tudo isso com um exemplo.
+
+Imagine que você tem um aplicativo que permite criar faturas.
+
+Essas faturas terão um `id`, `title` (opcional), `customer` e `total`.
+
+O usuário da sua API (um desenvolvedor externo) criará uma fatura em sua API com uma solicitação POST.
+
+Então sua API irá (vamos imaginar):
+
+* Enviar uma solicitação de pagamento para o desenvolvedor externo.
+* Coletar o dinheiro.
+* Enviar a notificação de volta para o usuário da API (o desenvolvedor externo).
+* Isso será feito enviando uma solicitação POST (de *sua API*) para alguma *API externa* fornecida por esse desenvolvedor externo (este é o "callback").
+
+## O aplicativo **FastAPI** normal
+
+Vamos primeiro ver como o aplicativo da API normal se pareceria antes de adicionar o callback.
+
+Ele terá uma *operação de rota* que receberá um corpo `Invoice`, e um parâmetro de consulta `callback_url` que conterá a URL para o callback.
+
+Essa parte é bastante normal, a maior parte do código provavelmente já é familiar para você:
+
+```Python hl_lines="9-13  36-53"
+{!../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+/// tip | Dica
+
+O parâmetro de consulta `callback_url` usa um tipo Pydantic Url.
+
+///
+
+A única coisa nova é o argumento `callbacks=invoices_callback_router.routes` no decorador da *operação de rota*. Veremos o que é isso a seguir.
+
+## Documentando o callback
+
+O código real do callback dependerá muito do seu próprio aplicativo de API.
+
+E provavelmente variará muito de um aplicativo para o outro.
+
+Poderia ser apenas uma ou duas linhas de código, como:
+
+```Python
+callback_url = "https://example.com/api/v1/invoices/events/"
+httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
+```
+
+Mas possivelmente a parte mais importante do callback é garantir que o usuário da sua API (o desenvolvedor externo) implemente a *API externa* corretamente, de acordo com os dados que *sua API* vai enviar no corpo da solicitação do callback, etc.
+
+Então, o que faremos a seguir é adicionar o código para documentar como essa *API externa* deve ser para receber o callback de *sua API*.
+
+A documentação aparecerá na interface do Swagger em `/docs` em sua API, e permitirá que os desenvolvedores externos saibam como construir a *API externa*.
+
+Esse exemplo não implementa o callback em si (que poderia ser apenas uma linha de código), apenas a parte da documentação.
+
+/// tip | Dica
+
+O callback real é apenas uma solicitação HTTP.
+
+Quando implementando o callback por você mesmo, você pode usar algo como HTTPX ou Requisições.
+
+///
+
+## Escrevendo o código de documentação do callback
+
+Esse código não será executado em seu aplicativo, nós só precisamos dele para *documentar* como essa *API externa* deveria ser.
+
+Mas, você já sabe como criar facilmente documentação automática para uma API com o **FastAPI**.
+
+Então vamos usar esse mesmo conhecimento para documentar como a *API externa* deveria ser... criando as *operações de rota* que a *API externa* deveria implementar (as que sua API irá chamar).
+
+/// tip | Dica
+
+Quando escrever o código para documentar um callback, pode ser útil imaginar que você é aquele *desenvolvedor externo*. E que você está atualmente implementando a *API externa*, não *sua API*.
+
+Adotar temporariamente esse ponto de vista (do *desenvolvedor externo*) pode ajudar a sentir que é mais óbvio onde colocar os parâmetros, o modelo Pydantic para o corpo, para a resposta, etc. para essa *API externa*.
+
+///
+
+### Criar um `APIRouter` para o callback
+
+Primeiramente crie um novo `APIRouter` que conterá um ou mais callbacks.
+
+```Python hl_lines="3  25"
+{!../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+### Crie a *operação de rota* do callback
+
+Para criar a *operação de rota* do callback, use o mesmo `APIRouter` que você criou acima.
+
+Ele deve parecer exatamente como uma *operação de rota* normal do FastAPI:
+
+* Ele provavelmente deveria ter uma declaração do corpo que deveria receber, por exemplo. `body: InvoiceEvent`.
+* E também deveria ter uma declaração de um código de status de resposta, por exemplo. `response_model=InvoiceEventReceived`.
+
+```Python hl_lines="16-18  21-22  28-32"
+{!../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+Há 2 diferenças principais de uma *operação de rota* normal:
+
+* Ela não necessita ter nenhum código real, porque seu aplicativo nunca chamará esse código. Ele é usado apenas para documentar a *API externa*. Então, a função poderia ter apenas `pass`.
+* A *rota* pode conter uma expressão OpenAPI 3 (veja mais abaixo) onde pode usar variáveis com parâmetros e partes da solicitação original enviada para *sua API*.
+
+### A expressão do caminho do callback
+
+A *rota* do callback pode ter uma expressão OpenAPI 3 que pode conter partes da solicitação original enviada para *sua API*.
+
+Nesse caso, é a `str`:
+
+```Python
+"{$callback_url}/invoices/{$request.body.id}"
+```
+
+Então, se o usuário da sua API (o desenvolvedor externo) enviar uma solicitação para *sua API* para:
+
+```
+https://yourapi.com/invoices/?callback_url=https://www.external.org/events
+```
+
+com um corpo JSON de:
+
+```JSON
+{
+    "id": "2expen51ve",
+    "customer": "Mr. [NAME_REDACTED]",
+    "total": "9999"
+}
+```
+
+então *sua API* processará a fatura e, em algum momento posterior, enviará uma solicitação de callback para o `callback_url` (a *API externa*):
+
+```
+https://www.external.org/events/invoices/2expen51ve
+```
+
+com um corpo JSON contendo algo como:
+
+```JSON
+{
+    "description": "Payment celebration",
+    "paid": true
+}
+```
+
+e esperaria uma resposta daquela *API externa* com um corpo JSON como:
+
+```JSON
+{
+    "ok": true
+}
+```
+
+/// tip | Dica
+
+Perceba como a URL de callback usada contém a URL recebida como um parâmetro de consulta em `callback_url` (`https://www.external.org/events`) e também o `id` da fatura de dentro do corpo JSON (`2expen51ve`).
+
+///
+
+### Adicionar o roteador de callback
+
+Nesse ponto você tem a(s) *operação de rota de callback* necessária(s) (a(s) que o *desenvolvedor externo* deveria implementar na *API externa*) no roteador de callback que você criou acima.
+
+Agora use o parâmetro `callbacks` no decorador da *operação de rota de sua API* para passar o atributo `.routes` (que é na verdade apenas uma `list` de rotas/*operações de rota*) do roteador de callback que você criou acima:
+
+```Python hl_lines="35"
+{!../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+/// tip | Dica
+
+Perceba que você não está passando o roteador em si (`invoices_callback_router`) para `callback=`, mas o atributo `.routes`, como em `invoices_callback_router.routes`.
+
+///
+
+### Verifique a documentação
+
+Agora você pode iniciar seu aplicativo e ir para http://127.0.0.1:8000/docs.
+
+Você verá sua documentação incluindo uma seção "Callbacks" para sua *operação de rota* que mostra como a *API externa* deveria ser:
+
+

Great work [USER_REDACTED] ✨

Just some lines that need to be removed, and some minor suggestions 😄

You've forgotten to remove this line 😄

Just a silly suggestion:

We alway start with a capital letter the translation of the admonitions

this line to :D

here to, just start with a capital letter if you want :D

This line needs to be removed to


🌐 Add Portuguese translation for `docs/pt/docs/advanced/middleware.md`

@@ -0,0 +1,96 @@
+# Middleware Avançado
+
+No tutorial principal você leu como adicionar [[NAME_REDACTED]](../tutorial/middleware.md){.internal-link target=_blank} à sua aplicação.
+
+E então você também leu como lidar com [CORS com o `CORSMiddleware`](../tutorial/cors.md){.internal-link target=_blank}.
+
+Nesta seção, veremos como usar outros middlewares.
+
+## Adicionando middlewares ASGI
+
+Como o **FastAPI** é baseado no Starlette e implementa a especificação ASGI, você pode usar qualquer middleware ASGI.
+
+O middleware não precisa ser feito para o FastAPI ou Starlette para funcionar, desde que siga a especificação ASGI.
+
+No geral, os middlewares ASGI são classes que esperam receber um aplicativo ASGI como o primeiro argumento.
+
+Então, na documentação de middlewares ASGI de terceiros, eles provavelmente dirão para você fazer algo como:
+
+```Python
+from unicorn import UnicornMiddleware
+
+app = SomeASGIApp()
+
+new_app = UnicornMiddleware(app, some_config="rainbow")
+```
+
+Mas, o FastAPI (na verdade, o Starlette) fornece uma maneira mais simples de fazer isso que garante que os middlewares internos lidem com erros do servidor e que os manipuladores de exceções personalizados funcionem corretamente.
+
+Para isso, você usa `app.add_middleware()` (como no exemplo para CORS).
+
+```Python
+from fastapi import FastAPI
+from unicorn import UnicornMiddleware
+
+app = FastAPI()
+
+app.add_middleware(UnicornMiddleware, some_config="rainbow")
+```
+
+`app.add_middleware()` recebe uma classe de middleware como o primeiro argumento e quaisquer argumentos adicionais a serem passados para o middleware.
+
+## [NAME_REDACTED]
+
+**FastAPI** inclui vários middlewares para casos de uso comuns, veremos a seguir como usá-los.
+
+/// note | Detalhes Técnicos
+
+Para o próximo exemplo, você também poderia usar `from starlette.middleware.something import SomethingMiddleware`.
+
+**FastAPI** fornece vários middlewares em `fastapi.middleware` apenas como uma conveniência para você, o desenvolvedor. Mas a maioria dos middlewares disponíveis vem diretamente do Starlette.
+
+///
+
+## `HTTPSRedirectMiddleware`
+
+Garante que todas as requisições devem ser `https` ou `wss`.
+
+Qualquer requisição para `http` ou `ws` será redirecionada para o esquema seguro.
+
+{* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *}
+
+## `TrustedHostMiddleware`
+
+Garante que todas as requisições recebidas tenham um cabeçalho `Host` corretamente configurado, a fim de proteger contra ataques de cabeçalho de host HTTP.
+
+{* ../../docs_src/advanced_middleware/tutorial002.py hl[2,6:8] *}
+
+Os seguintes argumentos são suportados:
+
+* `allowed_hosts` - Uma lista de nomes de domínio que são permitidos como nomes de host. Domínios com coringa, como `*.example.com`, são suportados para corresponder a subdomínios. Para permitir qualquer nome de host, use `allowed_hosts=["*"]` ou omita o middleware.
+
+Se uma requisição recebida não for validada corretamente, uma resposta `400` será enviada.
+
+## `GZipMiddleware`
+
+Gerencia respostas GZip para qualquer requisição que inclua `"gzip"` no cabeçalho `Accept-Encoding`.
+
+O middleware lidará com respostas padrão e de streaming.
+
+{* ../../docs_src/advanced_middleware/tutorial003.py hl[2,6] *}
+
+Os seguintes argumentos são suportados:
+
+* `minimum_size` - Não comprima respostas menores que este tamanho mínimo em bytes. O padrão é `500`.
+* `compresslevel` - Usado durante a compressão GZip. É um inteiro variando de 1 a 9. O padrão é `9`. Um valor menor resulta em uma compressão mais rápida, mas em arquivos maiores, enquanto um valor maior resulta em uma compressão mais lenta, mas em arquivos menores.
+
+## Outros middlewares
+
+Há muitos outros middlewares ASGI.
+
+Por exemplo:
+
+* Uvicorn's `ProxyHeadersMiddleware`
+* MessagePack
+
+Para checar outros middlewares disponíveis, confira Documentação de Middlewares do Starlette e a  Lista Incrível do ASGI.

Excellent, keep going with this kind of contribution.

nice work [USER_REDACTED]

Just a line that you've forgotten to remove, and a quote in the admonition

You can remove the quotes here:

```
/// note | Detalhes Técnicos
```

You've forgotten to remove this line 😄

oh haha, I'm sorry for that. I'll fix it!


BUG: fixed to_timedelta with list of int and float

- [x] closes #64044
- [x] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [x] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.
- [x] I have reviewed and followed all the [contribution guidelines](https://pandas.pydata.org/docs/dev/development/contributing.html)
- [ ] If I used AI to develop this pull request, I prompted it to follow `AGENTS.md`.

@@ -13,6 +13,7 @@ including other versions of pandas.

 Fixed regressions
 ~~~~~~~~~~~~~~~~~
+- Fixed regression in :func:`to_timedelta` when converting a list with float and int (:issue:`64044`)
 - Fixed regression in :meth:`DataFrame.groupby` and :meth:`Series.groupby` when grouping on categorical data with NA values, ``observed=False``, and ``dropna=True`` (:issue:`52445`)

 .. ---------------------------------------------------------------------------

@@ -509,6 +509,7 @@ def array_to_timedelta64(
                     ival = _numeric_to_td64ns(item, parsed_unit, NPY_FR_ns)

                     item_reso = NPY_FR_ns
+                    int_reso = NPY_FR_ns
                     state.update_creso(item_reso)
                     if infer_reso:
                         creso = state.creso

@@ -107,6 +107,14 @@ def test_to_timedelta_units(self):
         expected = to_timedelta([0, 10], unit="s").as_unit("ns")
         tm.assert_index_equal(result, expected)

+    def test_to_timedelta_mixed_dtype(self):
+        # https://github.com/[USER_REDACTED]ndas-dev/pandas/issues/64044
+        result = to_timedelta(np.array([0.5, 2]), unit="m")
+        expected = TimedeltaIndex(
+            ["0 days 00:00:30", "0 days 00:02:00"], dtype="timedelta64[ns]", freq=None
+        )
+        tm.assert_index_equal(result, expected)
+
     [USER_REDACTED].mark.parametrize(
         "dtype, unit",
         [

Thanks, looks good!

```suggestion
        # https://github.com/[USER_REDACTED]ndas-dev/pandas/issues/64044
        result = to_timedelta(np.array([0.5, 2]), unit="m")
```


BUG: fix dataframe reindex with string fill_value

- [x] closes #63993 (Replace xxxx with the GitHub issue number)
- [x] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
-  [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [x] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.
- [x] I have reviewed and followed all the [contribution guidelines](https://pandas.pydata.org/docs/dev/development/contributing.html)
- [ ] If I used AI to develop this pull request, I prompted it to follow `AGENTS.md`.

# BUG: Fix DataFrame.reindex with multiple columns and string fill_value

## [NAME_REDACTED] issue #63993 where `DataFrame.reindex` with multiple columns and a string `fill_value` raises `AssertionError` in pandas 3.0.0.

## [NAME_REDACTED] issue occurred in `pandas/core/internals/managers.py` in the `make_na_array` function. When reindexing with multiple columns and a string fill_value, pandas infers the new columns should have `str` dtype (a 1D-only ExtensionDtype). However, the function had an assertion `assert ncols == 1, ncols` that failed when trying to create multiple columns.

**Error:**
```python
pd.DataFrame({"a": [0]}).reindex(columns=["a", "b", "c"], fill_value="missing")
# AssertionError: 2
```

## [NAME_REDACTED] the `is_1d_only_ea_dtype` branch in `make_na_array` to handle multiple columns gracefully:

- **Single column**: Preserves original behavior (str dtype)
- **Multiple columns**: Falls back to object dtype for compatibility

This maintains backward compatibility while fixing the crash.

## Example

**Before (AssertionError):**
```python
df = pd.DataFrame({"a": [0]})
df.reindex(columns=["a", "b", "c"], fill_value="missing")  # AssertionError: 2
```

**After (Works):**
```python
df = pd.DataFrame({"a": [0]})
result = df.reindex(columns=["a", "b", "c"], fill_value="missing")
print(result)
#    a        b        c
# 0  0  missing  missing
```

Closes #63993

@@ -14,6 +14,7 @@ including other versions of pandas.
 Fixed regressions
 ~~~~~~~~~~~~~~~~~
 - Fixed regression in :meth:`DataFrame.groupby` and :meth:`Series.groupby` when grouping on categorical data with NA values, ``observed=False``, and ``dropna=True`` (:issue:`52445`)
+- Fixed regression in :meth:`DataFrame.reindex` when using a string fill value  (:issue:`63993`)
 - Fixed regression in the :class:`DataFrame` and :meth:`DataFrame.from_records` constructor with a list of dicts with a missing value indicator as key (:issue:`63889`)
 - Fixed regression when calling ``numpy.random``'s ``permutation()`` on a (pyarrow-backed) string :class:`Series` (:issue:`63935`)

@@ -956,11 +956,20 @@ def _slice_take_blocks_ax0(
             if blkno == -1:
                 # If we've got here, fill_value was not lib.no_default

-                yield self._make_na_block(
-                    placement=mgr_locs,
-                    fill_value=fill_value,
-                    use_na_proxy=use_na_proxy,
-                )
+                dtype, _ = infer_dtype_from_scalar(fill_value)
+                if is_1d_only_ea_dtype(dtype) and len(mgr_locs) > 1:
+                    # Handle 1D-only extension dtypes by [NAME_REDACTED]
+                    # (GH#63993)
+                    placements = [BlockPlacement(col_idx) for col_idx in mgr_locs]
+                else:
+                    placements = [mgr_locs]
+
+                for placement in placements:
+                    yield self._make_na_block(
+                        placement=placement,
+                        fill_value=fill_value,
+                        use_na_proxy=use_na_proxy,
+                    )
             else:
                 blk = self.blocks[blkno]

@@ -819,6 +819,13 @@ def test_reindex_single_column_ea_index_and_columns(self, any_numeric_ea_dtype):
         )
         tm.assert_frame_equal(result, expected)

+    def test_reindex_with_string_fill_value(self):
+        # GH#63993
+        df = DataFrame({"a": [0]})
+        result = df.reindex(columns=["a", "b", "c"], fill_value="missing")
+        expected = DataFrame({"a": [0], "b": ["missing"], "c": ["missing"]})
+        tm.assert_frame_equal(result, expected)
+
     def test_reindex_dups(self):
         # GH4746, reindex on duplicate index error messages
         arr = np.random.default_rng(2).standard_normal(10)

Looking good to me
Any edge case? [USER_REDACTED]

Looks good now! Just added a whatsnew note, and reduced the verbosity of the comments a bit.

I think you could try to simplify the change below by [NAME_REDACTED]_locs, and in the loop above also call `_make_na_block`, so then we should not need the new `_make_na_blocks` method that returns multiple blocks

Instead of asserting the individual values and dtypes, could you create the `expected = DataFrame(..)` and then assert_frame_equal(result, expected)

mypy complains about BlockPlacement([col_idx]) — BlockPlacement expects int/slice/ndarray, not list[int].
  Could you use BlockPlacement(col_idx) (or BlockPlacement(np.array([col_idx], dtype=np.intp))) instead?


DOC: clarify loc slice step behavior with example closes #63311

When using .loc[start:stop:step], start/stop use label semantics but step is positional within that range. Added example showing difference from explicit label selection.

<img width="987" height="702" alt="image" src="https://github.com/[USER_REDACTED]nts/assets/33df1c5c-528b-4b4b-a183-b4fbba6e38fe" />

Closes #63311

- [x] closes #63311
- [ ] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [ ] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.
- [ ] If I used AI to develop this pull request, I prompted it to follow `AGENTS.md`.

@@ -431,6 +431,36 @@ an error will be raised. For instance, in the above example, ``s.loc[2:5]`` woul
 For more information about duplicate labels, see
 :ref:`[NAME_REDACTED] <duplicates>`.

+When using a slice with a step, such as ``.loc[start:stop:step]``, note that
+*start* and *stop* are interpreted as **labels**, while *step* is applied over
+the **positional index** within that label range. This means a stepped slice
+will behave differently than using the labels ``range(start, stop, step)`` when
+the index is not contiguous integers.
+
+For example, in a ``Series`` with a non-contiguous integer index:
+
+.. ipython:: python
+
+    s = pd.Series(range(10), index=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45])
+    s.loc[10:50:5]              # (10), then skip 3 positions → 35 only
+    s.loc[[10, 15, 20, 25]]     # explicit label selection
+
+The first applies *step* across **positional locations** between the start/stop
+labels. The second selects each label directly.
+
+Similarly, with a string-based index, the behavior is identical:
+
+.. ipython:: python
+
+    s = pd.Series(range(10), index=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'])
+    s.loc['b':'i':2]            # Start at 'b' (position 1), stop at 'i' (position 8), step 2 positions → 'b', 'd', 'f', 'h'
+    s.loc[['b', 'd', 'f', 'h']] # explicit label selection
+
+In both cases, *start* and *stop* determine the label boundaries (inclusive),
+while *step* skips positions within that range, regardless of the index type.
+
+
+
 .. _indexing.integer:

 Selection by position

Looking good!

lgtm

Could you also show a similar example where the index is not numeric?

The previous paragraph also starts with `Also,`, just from a prose standpoint I think we should avoid this.

```suggestion
When using a slice with a step, such as ``.loc[start:stop:step]``, note that
```

I think this could be made a little more specific.

```suggestion
the **positional index** within that label range. This means a stepped slice
will behave differently than using the labels `range(start, stop, step)` when
the index is not contiguous integers.
```


BUG: ensure we still honor copy=True in Series constructor in all cases

Expanding the `Series(..)` constructor tests to cover all cases for copy=True vs False vs default None, and ensure we still honor `copy=True` when passing a Series or Index.

Triggered by [NAME_REDACTED] to describe that in the docstring for https://github.com/[USER_REDACTED]ndas-dev/pandas/pull/63341

@@ -403,6 +403,7 @@ def __init__(
             if copy is not False:
                 if dtype is None or astype_is_view(data.dtype, pandas_dtype(dtype)):
                     data = data.copy()
+                    copy = False
         if copy is None:
             copy = False

@@ -417,6 +418,7 @@ def __init__(
                     Pandas4Warning,
                     stacklevel=2,
                 )
+                allow_mgr = True

         name = ibase.maybe_extract_name(name, data, type(self))

@@ -442,9 +444,8 @@ def __init__(
         if isinstance(data, Index):
             if dtype is not None:
                 data = data.astype(dtype)
-
-            refs = data._references
-            copy = False
+            if not copy:
+                refs = data._references

         elif isinstance(data, np.ndarray):
             if len(data.dtype):
@@ -460,8 +461,9 @@ def __init__(
                 data = data._mgr.copy(deep=False)
             else:
                 data = data.reindex(index)
-                copy = False
                 data = data._mgr
+                if data._has_no_reference(0):
+                    copy = False
         elif isinstance(data, Mapping):
             data, index = self._init_dict(data, index, dtype)
             dtype = None
@@ -506,8 +508,10 @@ def __init__(
         # create/copy the manager
         if isinstance(data, SingleBlockManager):
             if dtype is not None:
+                if not astype_is_view(data.dtype, pandas_dtype(dtype)):
+                    copy = False
                 data = data.astype(dtype=dtype)
-            elif copy:
+            if copy:
                 data = data.copy(deep=True)
         else:
             data = sanitize_array(data, index, dtype, copy)

@@ -47,14 +47,24 @@ def test_series_from_series(dtype):
     ser.iloc[0] = 0
     assert result.iloc[0] == 1

+    # forcing copy=False still gives a CoW shallow copy
+    result = Series(ser, dtype=dtype, copy=False)
+    assert np.shares_memory(get_array(ser), get_array(result))
+    assert result._mgr.blocks[0].refs.has_reference()
+
+    # forcing copy=True still results in an actual hard copy up front
+    result = Series(ser, dtype=dtype, copy=True)
+    assert not np.shares_memory(get_array(ser), get_array(result))
+    assert ser._mgr._has_no_reference(0)
+

 def test_series_from_series_with_reindex():
     # Case: constructing a Series from another Series with specifying an index
     # that potentially requires a reindex of the values
     ser = Series([1, 2, 3], name="name")

     # passing an index that doesn't actually require a reindex of the values
-    # -> without CoW we get an actual mutating view
+    # -> still getting a CoW shallow copy
     for index in [
         ser.index,
         ser.index.copy(),
@@ -66,6 +76,11 @@ def test_series_from_series_with_reindex():
         result.iloc[0] = 0
         assert ser.iloc[0] == 1

+        # forcing copy=True still results in an actual hard copy up front
+        result = Series(ser, index=index, copy=True)
+        assert not np.shares_memory(ser.values, result.values)
+        assert not result._mgr.blocks[0].refs.has_reference()
+
     # ensure that if an actual reindex is needed, we don't have any refs
     # (mutating the result wouldn't trigger CoW)
     result = Series(ser, index=[0, 1, 2, 3])
@@ -87,6 +102,13 @@ def test_series_from_array(idx, dtype, arr):
     arr[0] = 100
     tm.assert_series_equal(ser, ser_orig)

+    # if the user explicitly passes copy=False, we get an actual view
+    # not protected by CoW
+    ser = Series(arr, dtype=dtype, index=idx, copy=False)
+    assert np.shares_memory(get_array(ser), data)
+    arr[0] = 50
+    assert ser.iloc[0] == 50
+

 [USER_REDACTED].mark.parametrize("copy", [True, False, None])
 def test_series_from_array_different_dtype(copy):
@@ -112,9 +134,22 @@ def test_series_from_index(idx):
     ser.iloc[0] = ser.iloc[1]
     tm.assert_index_equal(idx, expected)

+    # forcing copy=False still gives a CoW shallow copy
+    ser = Series(idx, copy=False)
+    assert np.shares_memory(get_array(ser), get_array(idx))
+    assert not ser._mgr._has_no_reference(0)
+    ser.iloc[0] = ser.iloc[1]
+    tm.assert_index_equal(idx, expected)
+
+    # forcing copy=True still results in a copy
+    ser = Series(idx, copy=True)
+    assert not np.shares_memory(get_array(ser), get_array(idx))
+    assert ser._mgr._has_no_reference(0)

-def test_series_from_index_different_dtypes():
-    idx = Index([1, 2, 3], dtype="int64")
+
+[USER_REDACTED].mark.parametrize("copy", [True, False, None])
+def test_series_from_index_different_dtypes(copy):
+    idx = Index([1, 2, 3], dtype="int64", copy=copy)
     ser = Series(idx, dtype="int32")
     assert not np.shares_memory(get_array(ser), get_array(idx))
     assert ser._mgr._has_no_reference(0)

LGTM just a merge conflict

Just confirming, does this impact the behavior/address https://github.com/[USER_REDACTED]ndas-dev/pandas/issues/63306?

No, because the default for Index input is `copy=False`. The only thing I am doing here is for the case when the user explicitly did `copy=True`, to in that case actually honor that and do a copy, instead of overriding it always to False and tracking the reference (as was done here in the removed code)

To avoid another copy later

To avoid raising this warning a second time below in some specific corner case

The reindex could in theory return a shallow copy instead of full copy (if the passed index is identical to `data`'s index), so the change here is to ensure that we only override copy to False if that did not happen (i.e. when there is no reference between the original and reindexed data).

That is to ensure that if the user specified `copy=True`, it will actually get a copy, and not a shallow copy, even in this case of reindexing.


DOC: update Series() docstring about copy behaviour

The docstring hasn't been fully updated for the new behaviour with CoW.

@@ -265,8 +265,14 @@ class Series(base.IndexOpsMixin, NDFrame):  # type: ignore[misc]
         See the :ref:`user guide <basics.dtypes>` for more usages.
     name : Hashable, default None
         The name to give to the Series.
-    copy : bool, default False
-        Copy input data. Only affects Series or 1d ndarray input. See examples.
+    copy : bool, default None
+        Whether to copy input data, only relevant for array, Series, and Index
+        inputs (for other input, e.g. a list, a new array is created anyway).
+        Defaults to True for array input and False for Index/Series.
+        Even when False for Index/Series, a shallow copy of the data is made.
+        Set to False to avoid copying array input at your own risk (if you
+        know the input data won't be modified elsewhere).
+        Set to True to force copying Series/Index input up front.

     See Also
     --------

lgtm

Related to https://github.com/[USER_REDACTED]ndas-dev/pandas/issues/63144, the question is what to put here in the docstring ..

`copy=None` is closest to what is in the signature, but is not really meaningful by itself. Of course, the behaviour also depends on the intput, so writing that it defaults to either True or False will also be misleading for some cases.
(eg the current `default False` in the docstring above is not correct for array input)

nit: no comma.

```suggestion
        Set to False to avoid copying array input at your own risk (if you
```

I'm fine with `None` here, I think the behavior is too complex to give a meaningful description in the space allowed.

It is the same as None, meaning a shallow copy (i.e. not copying right now, but still using CoW, so it is not that `copy=False` kind if disables CoW for this construction)

(added an explicit test for that in https://github.com/[USER_REDACTED]ndas-dev/pandas/pull/63342)

I was thinking to add something like:

```
Set to False to avoid copying array input ...
Set to True to force copying Series/Index input up front.
```

Would that be useful?

And then for the `copy=False` case for Series/Index input, I could also mention that when explaining the default, something like "For Series/Index input, a shallow copy of the data is made by default (same as `copy=False`)" (added the part between brackets)

That might make it clearer that essentially the default of copy=None is translated into copy=True for array input and copy=False for Series/Index input

> It's not quite clear to me what happens if you set it to False in the Series/Index case.

Ah, I had meant True (the non-default).

It is hard to evaluate without seeing the whole docstring. I'd think of starting with something like this:

> Whether to copy input data, only relevant for array, Series, and Index inputs. Defaults to True on array input and False on Index/Series. Even when False on Index/Series, a shallow copy of the data is made.