diff --git a/po/zh-TW.po b/po/zh-TW.po index c052a94b..67a5c5f7 100644 --- a/po/zh-TW.po +++ b/po/zh-TW.po @@ -9666,25 +9666,27 @@ msgstr "" #: src/error-handling.md:1 msgid "# Error Handling" -msgstr "" +msgstr "# 錯誤處理" #: src/error-handling.md:3 msgid "Error handling in Rust is done using explicit control flow:" -msgstr "" +msgstr "在 Rust 中,是透過明確的控制流程完成錯誤處理作業:" #: src/error-handling.md:5 msgid "" "* Functions that can have errors list this in their return type,\n" "* There are no exceptions." msgstr "" +"* 可能含有錯誤的函式會在回傳型別中列出相關資訊。\n" +"* 沒有任何例外。" #: src/error-handling/panics.md:1 msgid "# Panics" -msgstr "" +msgstr "# 恐慌" #: src/error-handling/panics.md:3 msgid "Rust will trigger a panic if a fatal error happens at runtime:" -msgstr "" +msgstr "如果執行階段發生重大錯誤,Rust 就會觸發恐慌:" #: src/error-handling/panics.md:5 msgid "" @@ -9695,6 +9697,12 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable,should_panic\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" println!(\"v[100]: {}\", v[100]);\n" +"}\n" +"```" #: src/error-handling/panics.md:12 msgid "" @@ -9702,16 +9710,19 @@ msgid "" " * Panics are symptoms of bugs in the program.\n" "* Use non-panicking APIs (such as `Vec::get`) if crashing is not acceptable." msgstr "" +"* 恐慌代表發生無法復原的非預期錯誤。\n" +"* 恐慌可以反映程式中的錯誤。\n" +"* 如果無法接受程式崩潰,請使用不會觸發恐慌的 API,例如 `Vec::get`。" #: src/error-handling/panic-unwind.md:1 msgid "# Catching the Stack Unwinding" -msgstr "" +msgstr "# 擷取解開堆疊的動作" #: src/error-handling/panic-unwind.md:3 msgid "" "By default, a panic will cause the stack to unwind. The unwinding can be " "caught:" -msgstr "" +msgstr "根據預設,恐慌會造成解開堆疊。您可以擷取這類動作:" #: src/error-handling/panic-unwind.md:5 msgid "" @@ -9729,17 +9740,33 @@ msgid "" "assert!(result.is_err());\n" "```" msgstr "" +"```rust,editable\n" +"use std::panic;\n" +"\n" +"let result = panic::catch_unwind(|| {\n" +" println!(\"hello!\");\n" +"});\n" +"assert!(result.is_ok());\n" +"\n" +"let result = panic::catch_unwind(|| {\n" +" panic!(\"oh no!\");\n" +"});\n" +"assert!(result.is_err());\n" +"```" -#: src/error-handling/panic-unwind.md:19 +#: src/error-handling/panic-unwind.md:21 msgid "" "* This can be useful in servers which should keep running even if a single\n" " request crashes.\n" "* This does not work if `panic = 'abort'` is set in your `Cargo.toml`." msgstr "" +"* 如果伺服器需要持續運作 (即使有單一要求崩潰也不例外),這種做法就能派上用" +"場。\n" +"* 如果您在 `Cargo.toml` 中設定 `panic = 'abort'`,就無法採取此做法。" #: src/error-handling/result.md:1 msgid "# Structured Error Handling with `Result`" -msgstr "" +msgstr "# 使用 `Result` 進行結構化錯誤處理" #: src/error-handling/result.md:3 msgid "" @@ -9747,6 +9774,8 @@ msgid "" "are\n" "expected as part of normal operation:" msgstr "" +"我們先前介紹了 `Result` 列舉。當正常運作過程中預期發生錯誤時,普遍都會使用這" +"個列舉:" #: src/error-handling/result.md:6 msgid "" @@ -9769,6 +9798,24 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"use std::fs::File;\n" +"use std::io::Read;\n" +"\n" +"fn main() {\n" +" let file = File::open(\"diary.txt\");\n" +" match file {\n" +" Ok(mut file) => {\n" +" let mut contents = String::new();\n" +" file.read_to_string(&mut contents);\n" +" println!(\"Dear diary: {contents}\");\n" +" },\n" +" Err(err) => {\n" +" println!(\"The diary could not be opened: {err}\");\n" +" }\n" +" }\n" +"}\n" +"```" #: src/error-handling/result.md:27 msgid "" @@ -9782,19 +9829,18 @@ msgid "" "it is worth mentioning. \n" " It contains a lot of convenience methods and functions that help " "functional-style programming. \n" -" " msgstr "" #: src/error-handling/try-operator.md:1 msgid "# Propagating Errors with `?`" -msgstr "" +msgstr "# 使用 `?` 傳播錯誤" #: src/error-handling/try-operator.md:3 msgid "" "The try-operator `?` is used to return errors to the caller. It lets you " "turn\n" "the common" -msgstr "" +msgstr "try 運算子 `?` 用於將錯誤傳回呼叫端,讓您將下列常見的程式碼:" #: src/error-handling/try-operator.md:6 msgid "" @@ -9805,10 +9851,16 @@ msgid "" "}\n" "```" msgstr "" +"```rust,ignore\n" +"match some_expression {\n" +" Ok(value) => value,\n" +" Err(err) => return Err(err),\n" +"}\n" +"```" #: src/error-handling/try-operator.md:13 msgid "into the much simpler" -msgstr "" +msgstr "轉換成以下較簡潔的程式碼:" #: src/error-handling/try-operator.md:15 msgid "" @@ -9816,10 +9868,13 @@ msgid "" "some_expression?\n" "```" msgstr "" +"```rust,ignore\n" +"some_expression?\n" +"```" #: src/error-handling/try-operator.md:19 msgid "We can use this to simplify our error handing code:" -msgstr "" +msgstr "我們可以使用這個運算子,簡化錯誤處理程式碼:" #: src/error-handling/try-operator.md:21 msgid "" @@ -9848,6 +9903,30 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"use std::fs;\n" +"use std::io::{self, Read};\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let username_file_result = fs::File::open(path);\n" +" let mut username_file = match username_file_result {\n" +" Ok(file) => file,\n" +" Err(err) => return Err(err),\n" +" };\n" +"\n" +" let mut username = String::new();\n" +" match username_file.read_to_string(&mut username) {\n" +" Ok(_) => Ok(username),\n" +" Err(err) => Err(err),\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"alice\").unwrap();\n" +" let username = read_username(\"config.dat\");\n" +" println!(\"username or error: {username:?}\");\n" +"}\n" +"```" #: src/error-handling/try-operator.md:50 #: src/error-handling/converting-error-types-example.md:52 @@ -9860,13 +9939,13 @@ msgstr "" #: src/error-handling/converting-error-types.md:1 #: src/error-handling/converting-error-types-example.md:1 msgid "# Converting Error Types" -msgstr "" +msgstr "# 轉換錯誤類型" #: src/error-handling/converting-error-types.md:3 msgid "" "The effective expansion of `?` is a little more complicated than previously " "indicated:" -msgstr "" +msgstr "比起先前提到的下列程式碼,`?` 的有效擴展稍微更複雜一點:" #: src/error-handling/converting-error-types.md:5 msgid "" @@ -9874,10 +9953,13 @@ msgid "" "expression?\n" "```" msgstr "" +"```rust,ignore\n" +"expression?\n" +"```" #: src/error-handling/converting-error-types.md:9 msgid "works the same as" -msgstr "" +msgstr "運作方式與以下程式碼相同:" #: src/error-handling/converting-error-types.md:11 msgid "" @@ -9888,6 +9970,12 @@ msgid "" "}\n" "```" msgstr "" +"```rust,ignore\n" +"match expression {\n" +" Ok(value) => value,\n" +" Err(err) => return Err(From::from(err)),\n" +"}\n" +"```" #: src/error-handling/converting-error-types.md:18 msgid "" @@ -9895,6 +9983,7 @@ msgid "" "the\n" "type returned by the function:" msgstr "" +"這裡的 `From::from` 呼叫意味著,我們嘗試將錯誤型別轉換成函式回傳的型別:" #: src/error-handling/converting-error-types-example.md:3 msgid "" @@ -9944,6 +10033,50 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"use std::error::Error;\n" +"use std::fmt::{self, Display, Formatter};\n" +"use std::fs::{self, File};\n" +"use std::io::{self, Read};\n" +"\n" +"#[derive(Debug)]\n" +"enum ReadUsernameError {\n" +" IoError(io::Error),\n" +" EmptyUsername(String),\n" +"}\n" +"\n" +"impl Error for ReadUsernameError {}\n" +"\n" +"impl Display for ReadUsernameError {\n" +" fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n" +" match self {\n" +" Self::IoError(e) => write!(f, \"IO error: {e}\"),\n" +" Self::EmptyUsername(filename) => write!(f, \"Found no username in {filename}\"),\n" +" }\n" +" }\n" +"}\n" +"\n" +"impl From for ReadUsernameError {\n" +" fn from(err: io::Error) -> ReadUsernameError {\n" +" ReadUsernameError::IoError(err)\n" +" }\n" +"}\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" let username = read_username(\"config.dat\");\n" +" println!(\"username or error: {username:?}\");\n" +"}\n" +"```" #: src/error-handling/converting-error-types-example.md:55 msgid "" @@ -9958,7 +10091,7 @@ msgstr "" #: src/error-handling/deriving-error-enums.md:1 msgid "# Deriving Error Enums" -msgstr "" +msgstr "# 推導錯誤列舉" #: src/error-handling/deriving-error-enums.md:3 msgid "" @@ -9966,6 +10099,8 @@ msgid "" "an\n" "error enum like we did on the previous page:" msgstr "" +"[thiserror](https://docs.rs/thiserror/) crate 很常用來建立錯誤列舉,我們在上" +"一頁就曾這麼做:" #: src/error-handling/deriving-error-enums.md:6 msgid "" @@ -10000,6 +10135,36 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable,compile_fail\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" +"use thiserror::Error;\n" +"\n" +"#[derive(Debug, Error)]\n" +"enum ReadUsernameError {\n" +" #[error(\"Could not read: {0}\")]\n" +" IoError(#[from] io::Error),\n" +" #[error(\"Found no username in {0}\")]\n" +" EmptyUsername(String),\n" +"}\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" fs::File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err}\"),\n" +" }\n" +"}\n" +"```" #: src/error-handling/deriving-error-enums.md:39 msgid "" @@ -10016,7 +10181,7 @@ msgstr "" #: src/error-handling/dynamic-errors.md:1 msgid "# Dynamic Error Types" -msgstr "" +msgstr "# 動態錯誤型別" #: src/error-handling/dynamic-errors.md:3 msgid "" @@ -10024,6 +10189,8 @@ msgid "" "our own enum covering\n" "all the different possibilities. `std::error::Error` makes this easy." msgstr "" +"我們有時會想允許傳回任何型別的錯誤,而不是自行編寫涵蓋所有不同可能性的列舉。" +"`std::error::Error` 可讓這項工作更輕鬆。" #: src/error-handling/dynamic-errors.md:6 msgid "" @@ -10055,6 +10222,33 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable,compile_fail\n" +"use std::fs::{self, File};\n" +"use std::io::Read;\n" +"use thiserror::Error;\n" +"use std::error::Error;\n" +"\n" +"#[derive(Clone, Debug, Eq, Error, PartialEq)]\n" +"#[error(\"Found no username in {0}\")]\n" +"struct EmptyUsernameError(String);\n" +"\n" +"fn read_username(path: &str) -> Result> {\n" +" let mut username = String::with_capacity(100);\n" +" File::open(path)?.read_to_string(&mut username)?;\n" +" if username.is_empty() {\n" +" return Err(EmptyUsernameError(String::from(path)).into());\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err}\"),\n" +" }\n" +"}\n" +"```" #: src/error-handling/dynamic-errors.md:36 msgid "" @@ -10069,7 +10263,7 @@ msgstr "" #: src/error-handling/error-contexts.md:1 msgid "# Adding Context to Errors" -msgstr "" +msgstr "# 為錯誤添加背景資訊" #: src/error-handling/error-contexts.md:3 msgid "" @@ -10077,6 +10271,8 @@ msgid "" "contextual information to your errors and allows you to have fewer\n" "custom error types:" msgstr "" +"透過廣泛使用的 [anyhow](https://docs.rs/anyhow/) crate,您可以為錯誤添加背景" +"資訊,並減少自訂錯誤型別的數量:" #: src/error-handling/error-contexts.md:7 msgid "" @@ -10106,6 +10302,31 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable,compile_fail\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" +"use anyhow::{Context, Result, bail};\n" +"\n" +"fn read_username(path: &str) -> Result {\n" +" let mut username = String::with_capacity(100);\n" +" fs::File::open(path)\n" +" .with_context(|| format!(\"Failed to open {path}\"))?\n" +" .read_to_string(&mut username)\n" +" .context(\"Failed to read\")?;\n" +" if username.is_empty() {\n" +" bail!(\"Found no username in {path}\");\n" +" }\n" +" Ok(username)\n" +"}\n" +"\n" +"fn main() {\n" +" //fs::write(\"config.dat\", \"\").unwrap();\n" +" match read_username(\"config.dat\") {\n" +" Ok(username) => println!(\"Username: {username}\"),\n" +" Err(err) => println!(\"Error: {err:?}\"),\n" +" }\n" +"}\n" +"```" #: src/error-handling/error-contexts.md:35 msgid ""