1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-02-04 18:36:01 +02:00

Parse Markdown in mdbook-xgettext (#449)

* Parse Markdown to support translation.

This upgrades from just splitting Markdown files on double-newlines, to
using a Markdown parser to break them into more appropriate chunks. The
upshot is that code samples are all in one message, lists are bundled
together, and generally it should be easier to translate.

* [WIP] helper to update po files for new translation

* process synthetic input file-by-file

* review comments

* remove temporary code

* fix msgfmt lints
This commit is contained in:
Dustin J. Mitchell 2023-03-07 13:07:07 -05:00 committed by GitHub
parent 3242afae09
commit ba28dd2d4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 604 additions and 694 deletions

3
Cargo.lock generated
View File

@ -778,9 +778,8 @@ version = "0.1.0"
dependencies = [
"anyhow",
"mdbook",
"once_cell",
"polib",
"regex",
"pulldown-cmark",
"semver",
"serde_json",
"toml",

View File

@ -7,9 +7,8 @@ publish = false
[dependencies]
anyhow = "1.0.68"
mdbook = "0.4.25"
once_cell = "1.17.0"
polib = "0.1.0"
regex = "1.7.0"
pulldown-cmark = { version = "0.9.2", default-features = false }
semver = "1.0.16"
serde_json = "1.0.91"
toml = "0.5.1"

View File

@ -26,7 +26,7 @@
//! See `TRANSLATIONS.md` in the repository root for more information.
use anyhow::{anyhow, Context};
use i18n_helpers::extract_paragraphs;
use i18n_helpers::extract_msgs;
use mdbook::book::Book;
use mdbook::preprocess::{CmdPreprocessor, PreprocessorContext};
use mdbook::BookItem;
@ -38,31 +38,32 @@ use std::process;
use toml::Value;
fn translate(text: &str, catalog: &Catalog) -> String {
let mut consumed = 0; // bytes of text consumed so far
let mut output = String::with_capacity(text.len());
let mut target_lineno = 1;
for (lineno, paragraph) in extract_paragraphs(text) {
// Fill in blank lines between paragraphs. This is important
// for code blocks where blank lines are significant.
while target_lineno < lineno {
output.push('\n');
target_lineno += 1;
for msg in extract_msgs(text) {
let span = msg.span();
// Copy over any bytes of text that precede this message.
if consumed < span.start {
output.push_str(&text[consumed..span.start]);
}
// Subtract 1 because the paragraph is missing a final '\n'
// due to the splitting in `extract_paragraphs`.
target_lineno += paragraph.lines().count() - 1;
// Insert the translated text
let msg_text = msg.text(text);
let translated = catalog
.find_message(paragraph)
.find_message(msg_text)
.filter(|msg| !msg.flags.contains("fuzzy"))
.and_then(|msg| msg.get_msgstr().ok())
.filter(|msgstr| !msgstr.is_empty())
.map(|msgstr| msgstr.as_str())
.unwrap_or(paragraph);
.unwrap_or(msg_text);
output.push_str(translated);
consumed = span.end;
}
let suffix = &text[text.trim_end_matches('\n').len()..];
// Handle any text left over after the last message.
let suffix = &text[consumed..];
output.push_str(suffix);
output
}

View File

@ -91,10 +91,10 @@ fn create_catalog(ctx: &RenderContext) -> anyhow::Result<Catalog> {
Some(path) => ctx.config.book.src.join(path),
None => continue,
};
for (lineno, paragraph) in i18n_helpers::extract_paragraphs(&chapter.content)
for msg in i18n_helpers::extract_msgs(&chapter.content)
{
let source = format!("{}:{}", path.display(), lineno);
add_message(&mut catalog, paragraph, &source);
let source = format!("{}:{}", path.display(), msg.line_number());
add_message(&mut catalog, msg.text(&chapter.content), &source);
}
}
}

View File

@ -12,112 +12,486 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use once_cell::sync::Lazy;
use regex::Regex;
use mdbook::utils::new_cmark_parser;
use pulldown_cmark::{Event, Tag};
use std::ops::Range;
static PARAGRAPH_SEPARATOR: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n\n+").unwrap());
/// A translatable message.
#[derive(PartialEq, Debug)]
pub struct Message {
/// Line number where this message begins.
line: usize,
/// Extract paragraphs from text.
///
/// Paragraphs are separated by at least two newlines. Returns an
/// iterator over line numbers (starting from 1) and paragraphs.
pub fn extract_paragraphs(text: &str) -> impl Iterator<Item = (usize, &str)> {
// TODO: This could be made more sophisticated by parsing the
// Markdown and stripping off the markup characters.
//
// As an example, a header like "## My heading" could become just
// "My heading" in the `.pot` file. Similarly, paragraphs could be
// unfolded and list items could be translated one-by-one.
/// Span of the input text containing this message.
span: Range<usize>,
}
// Skip over leading empty lines.
let trimmed = text.trim_start_matches('\n');
let mut matches = PARAGRAPH_SEPARATOR.find_iter(trimmed);
let mut lineno = 1 + text.len() - trimmed.len();
let mut last = 0;
impl Message {
fn new(line: usize, span: Range<usize>) -> Self {
Self { line, span }
}
std::iter::from_fn(move || match matches.next() {
Some(m) => {
let result = (lineno, &trimmed[last..m.start()]);
lineno += trimmed[last..m.end()].lines().count();
last = m.end();
Some(result)
/// Get the text of this message, as a slice of the document from which it was generated.
pub fn text<'doc>(&self, document: &'doc str) -> &'doc str {
&document[self.span.clone()]
}
/// Get the line number at which this message begins.
pub fn line_number(&self) -> usize {
self.line
}
/// Get the span of the source document from which this message is drawn.
pub fn span(&self) -> Range<usize> {
self.span.clone()
}
/// Extend this message to the given offset.
fn extend(&mut self, to_end: usize) {
self.span.end = to_end;
}
/// Trim trailing newlines from this message.
fn trim_right(&mut self, document: &str) {
let trimmed_len = document[self.span.clone()].trim_end_matches('\n').len();
self.span.end = self.span.start + trimmed_len;
}
}
/// Accumulator for translatable messages based on input from the Markdown parser.
struct MsgAccumulator<'a> {
/// The input document.
document: &'a str,
/// Offsets of each newline in the input, used to calculate line numbers from byte offsets.
offsets: Vec<usize>,
/// The resulting messages, as ranges of the input document.
msgs: Vec<Message>,
/// Current nesting depth of Start/End events.
depth: usize,
/// If set, skip until the nesting depth returns to this level.
skip_until_depth: Option<usize>,
/// True if the last message can still be appended to. If this is true then
/// msgs has at least one element.
message_open: bool,
}
impl<'a> MsgAccumulator<'a> {
fn new(document: &'a str) -> Self {
Self {
document: document,
offsets: document
.match_indices("\n")
.map(|(offset, _)| offset)
.collect(),
msgs: vec![],
depth: 0,
skip_until_depth: None,
message_open: false,
}
None => {
if last < trimmed.len() {
let result = (lineno, trimmed[last..].trim_end_matches('\n'));
last = trimmed.len();
Some(result)
} else {
None
}
/// Mark the current message as finished.
fn finish_message(&mut self) {
self.message_open = false;
}
/// Add a new text message, or extend an existing one.
fn push_message(&mut self, span: Range<usize>) {
// try to combine with an existing message.
if self.message_open {
if let Some(last) = self.msgs.last_mut() {
last.extend(span.end);
return;
}
}
})
self.msgs
.push(Message::new(self.line_number(span.start), span));
self.message_open = true;
}
/// Calculate the line number for the given offset.
fn line_number(&self, offset: usize) -> usize {
self.offsets.partition_point(|&o| o < offset) + 1
}
/// Push a new Markdown event into the accumulator.
fn push_event(&mut self, evt: Event<'a>, span: Range<usize>) {
#[cfg(test)]
println!("{evt:?} -- {:?}", &self.document[span.start..span.end]);
// Track the nesting depth.
match evt {
Event::Start(_) => self.depth += 1,
Event::End(_) => self.depth -= 1,
_ => {}
}
// Handle skip_until_depth, including skipping the End event that
// returned to the desired level.
if let Some(depth) = self.skip_until_depth {
if self.depth <= depth {
self.skip_until_depth = None;
}
return;
}
match evt {
// Consider "inline" tags to be just part of the text.
Event::Start(
Tag::Emphasis | Tag::Strong | Tag::Strikethrough | Tag::Link(..),
) => self.push_message(span),
Event::End(
Tag::Emphasis | Tag::Strong | Tag::Strikethrough | Tag::Link(..),
) => self.push_message(span),
// We want to translate everything: text, code (from backticks, `..`), or HTML.
Event::Text(_) | Event::Code(_) | Event::Html(_) => self.push_message(span),
// For many event types we just take the entire text from Start to End, which is
// already encompassed in the event span.
Event::Start(
Tag::CodeBlock(_)
| Tag::Heading(..)
| Tag::List(..)
| Tag::BlockQuote
| Tag::Table(..),
) => {
self.finish_message();
self.push_message(span);
self.finish_message();
// Skip until we get to a nesting depth outside of this Start event.
self.skip_until_depth = Some(self.depth - 1);
}
// For any other Start or End events, finish the current message but do
// not begin a new one.
Event::Start(_) | Event::End(_) => self.finish_message(),
_ => {}
}
}
/// Get the resulting list of messages.
fn into_msgs(mut self) -> Vec<Message> {
let parser = new_cmark_parser(self.document, false);
for (evt, span) in parser.into_offset_iter() {
self.push_event(evt, span);
}
for msg in &mut self.msgs {
msg.trim_right(self.document);
}
self.msgs
}
}
/// Extract translatable messages from the markdown text.
///
/// Returns a vector of (line number, text), where line numbers begin at 1.
pub fn extract_msgs(document: &str) -> Vec<Message> {
MsgAccumulator::new(document).into_msgs()
}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! assert_iter_eq {
($left_iter:expr, $right:expr) => {
assert_eq!($left_iter.collect::<Vec<_>>(), $right)
};
#[test]
fn offset_to_line_empty() {
assert_eq!(MsgAccumulator::new("").line_number(0), 1);
}
#[test]
fn test_extract_paragraphs_empty() {
assert_iter_eq!(extract_paragraphs(""), vec![]);
}
fn offset_to_line_multiline() {
let input = "abc\ndef\nghi";
let acc = MsgAccumulator::new(input);
let line_nums: Vec<_> = input
.chars()
.enumerate()
.map(|(idx, ch)| (acc.line_number(idx), ch))
.collect();
#[test]
fn test_extract_paragraphs_single_line() {
assert_iter_eq!(
extract_paragraphs("This is a paragraph."),
vec![(1, "This is a paragraph.")]
assert_eq!(
line_nums,
vec![
(1, 'a'),
(1, 'b'),
(1, 'c'),
(1, '\n'),
(2, 'd'),
(2, 'e'),
(2, 'f'),
(2, '\n'),
(3, 'g'),
(3, 'h'),
(3, 'i'),
]
);
}
fn msg_to_tuple<'doc>(msg: &Message, document: &'doc str) -> (usize, &'doc str) {
(msg.line_number(), msg.text(document))
}
macro_rules! assert_extract_msgs {
($document:expr, $exp:expr) => {{
let document = $document;
assert_eq!(
extract_msgs(document)
.iter()
.map(|m| msg_to_tuple(m, document))
.collect::<Vec<_>>(),
$exp
)
}};
}
#[test]
fn test_extract_paragraphs_simple() {
assert_iter_eq!(
extract_paragraphs(
"This is\n\
fn extract_msgs_empty() {
assert_extract_msgs!("", vec![]);
}
#[test]
fn extract_msgs_single_line() {
assert_extract_msgs!("This is a paragraph.", vec![(1, "This is a paragraph.")]);
}
#[test]
fn extract_msgs_simple() {
assert_extract_msgs!(
"This is\n\
the first\n\
paragraph.\n\
paragraph.🦀\n\
\n\
Second paragraph."
),
Second paragraph.",
vec![
(1, "This is\nthe first\nparagraph."),
(1, "This is\nthe first\nparagraph.🦀"),
(5, "Second paragraph.")
]
);
}
#[test]
fn test_extract_paragraphs_leading_newlines() {
assert_iter_eq!(
extract_paragraphs(
"\n\
fn extract_msgs_leading_newlines() {
assert_extract_msgs!(
"\n\
\n\
\n\
This is the\n\
first paragraph."
),
first paragraph.",
vec![(4, "This is the\nfirst paragraph.")]
);
}
#[test]
fn test_extract_paragraphs_trailing_newlines() {
assert_iter_eq!(
extract_paragraphs(
"This is\n\
fn extract_msgs_trailing_newlines() {
assert_extract_msgs!(
"This is\n\
a paragraph.\n\
\n\
\n"
),
\n",
vec![(1, "This is\na paragraph.")]
);
}
#[test]
fn extract_msgs_styled_text() {
assert_extract_msgs!(
"**This** ~~message~~ _has_ `code` *style*\n",
vec![(1, "**This** ~~message~~ _has_ `code` *style*")]
);
}
#[test]
fn extract_msgs_inline_html() {
assert_extract_msgs!(
"Hi <script>alert('there');</script>",
vec![(1, "Hi <script>alert('there');</script>")]
);
}
#[test]
fn extract_msgs_links() {
assert_extract_msgs!(
"See [this page](https://example.com) for more info.",
vec![(1, "See [this page](https://example.com) for more info.")]
);
}
#[test]
fn extract_msgs_links_footer() {
assert_extract_msgs!(
r#"
* [Brazilian Portuguese][pt-BR] and
* [Korean][ko]
[pt-BR]: https://google.github.io/comprehensive-rust/pt-BR/
[ko]: https://google.github.io/comprehensive-rust/ko/
"#,
// The parser does not include the referenced links in the events it produces. This is
// probably OK: links would not have been translated, anyway.
vec![(2, "* [Brazilian Portuguese][pt-BR] and\n* [Korean][ko]"),]
);
}
#[test]
fn extract_msgs_block_quote() {
assert_extract_msgs!(
r#"One of my favorite quotes is:
> Don't believe everything you read on the Internet.
>
> I didn't say this second part, but I needed a paragraph for testing.
--Abraham Lincoln
"#,
vec![
(1, "One of my favorite quotes is:"),
(3, "> Don't believe everything you read on the Internet.\n>\n> I didn't say this second part, but I needed a paragraph for testing."),
(7, "--Abraham Lincoln"),
]
);
}
#[test]
fn extract_msgs_table() {
let table = r#"| Module Type | Description
|-------------------|------------------------------------------------------------------------
| `rust_binary` | Produces a Rust binary.
| `rust_library` | Produces a Rust library, and provides both `rlib` and `dylib` variants."#;
let input = format!("Hey, a table\n\n{table}\n\nFooter.\n");
// tables are included as part of the text.
assert_extract_msgs!(
&input,
vec![(1, "Hey, a table"), (3, table), (8, "Footer."),]
);
}
#[test]
fn extract_msgs_code_block() {
assert_extract_msgs!("Preamble\n```rust\nfn hello() {\n some_code()\n\n todo!()\n}\n```\nPostamble",
vec![
(1, "Preamble"),
(2, "```rust\nfn hello() {\n some_code()\n\n todo!()\n}\n```"),
(9, "Postamble")
]
);
}
#[test]
fn extract_msgs_details() {
// This isn't great, because the parser treats any data following a tag as also HTML,
// but works well enough when `<details>` has blank lines before and after.
assert_extract_msgs!(
"Preamble\n<details>\nSome Details\n</details>\n\nPostamble",
vec![
(1, "Preamble"),
(2, "<details>\nSome Details\n</details>"),
(6, "Postamble")
]
);
assert_extract_msgs!(
"Preamble\n\n<details>\n\nSome Details\n\n</details>\n\nPostamble",
vec![
(1, "Preamble"),
(3, "<details>"),
(5, "Some Details"),
(7, "</details>"),
(9, "Postamble")
]
);
}
#[test]
fn extract_msgs_list() {
assert_extract_msgs!(
"Some text\n * List item 1🦀\n * List item 2\n\nMore text",
vec![
(1, "Some text"),
(2, " * List item 1🦀\n * List item 2"),
(5, "More text")
]
);
}
#[test]
fn extract_msgs_multilevel_list() {
assert_extract_msgs!("Some text\n * List item 1\n * List item 2\n * Sublist 1\n * Sublist 2\n\nMore text",
vec![
(1, "Some text"),
(2, " * List item 1\n * List item 2\n * Sublist 1\n * Sublist 2"),
(7, "More text")
]
);
}
#[test]
fn extract_msgs_list_with_paras() {
assert_extract_msgs!(
r#"* Item 1.
* Item 2,
two lines.
* Sub 1.
* Sub 2.
More paragraph.
Top level.
"#,
vec![
(1, "* Item 1.\n* Item 2,\n two lines.\n\n * Sub 1.\n * Sub 2.\n\n More paragraph."),
(10, "Top level."),
]
);
}
#[test]
fn extract_msgs_headings() {
assert_extract_msgs!(
r#"Some text
# Headline News🦀
* A
* List
## Subheading
"#,
vec![
(1, "Some text"),
(2, "# Headline News🦀"),
(4, "* A\n* List"),
(7, "## Subheading")
]
);
}
#[test]
fn extract_msgs_code_followed_by_details() {
// This is a regression test for an error that would incorrectly combine
// CodeBlock and HTML.
assert_extract_msgs!(
r#"```bob
BOB
```
<details>
* Blah blah
</details>
"#,
vec![
(1, "```bob\nBOB\n```"),
(5, "<details>"),
(7, "* Blah blah"),
(9, "</details>"),
]
);
}
}

View File

@ -2061,12 +2061,14 @@ msgstr ""
#: src/basic-syntax/compound-types.md:28
msgid ""
"<details>\n"
" \n"
"Key points:\n"
" \n"
msgstr ""
msgid ""
"Arrays:\n"
" \n"
msgstr ""
msgid ""
"* Arrays have elements of the same type, `T`, and length, `N`, which is a "
"compile-time constant."
msgstr ""
@ -3750,6 +3752,9 @@ msgstr ""
#: src/ownership/borrowing.md:27
msgid ""
"Notes on stack returns:\n"
msgstr ""
msgid ""
"* Demonstrate that the return from `add` is cheap because the compiler can "
"eliminate the copy operation. Change the above code to print stack addresses "
"and run it on the [Playground]. In the \"DEBUG\" optimization level, the "
@ -3782,7 +3787,9 @@ msgid ""
" println!(\"&p3.0: {:p}\", &p3.0);\n"
" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n"
" }\n"
" ```\n"
msgstr ""
msgid ""
"* The Rust compiler can do return value optimization (RVO).\n"
"* In C++, copy elision has to be defined in the language specification "
"because constructors can have side effects. In Rust, this is not an issue at "
@ -10942,7 +10949,9 @@ msgid ""
" println!(\"transposed:\");\n"
" pretty_print(&transposed);\n"
"}\n"
"```\n"
msgstr ""
msgid ""
"### Bonus question"
msgstr ""

154
po/de.po
View File

@ -2608,15 +2608,6 @@ msgstr ""
"* Referenzen, die als `mut` deklariert sind, können über ihre Lebensdauer an unterschiedliche "
"Werte gebunden werden."
#: src/basic-syntax/references.md:21
#, fuzzy
msgid ""
"<details>\n"
"Key points:"
msgstr ""
"<Details>\n"
"Kernpunkte:"
#: src/basic-syntax/references.md:24
#, fuzzy
msgid ""
@ -3524,16 +3515,17 @@ msgstr ""
msgid ""
"This slide demonstrates how the Rust compiler infers types based on constraints given by variable "
"declarations and usages.\n"
" \n"
msgstr ""
"Diese Folie zeigt, wie der Rust-Compiler Typen basierend auf Einschränkungen ableitet, die durch "
"Variablendeklarationen und Verwendungen gegeben sind.\n"
msgid ""
"It is very important to emphasize that variables declared like this are not of some sort of "
"dynamic \"any type\" that can\n"
"hold any data. The machine code generated by such declaration is identical to the explicit "
"declaration of a type.\n"
"The compiler does the job for us and helps us to write a more concise code."
msgstr ""
"Diese Folie zeigt, wie der Rust-Compiler Typen basierend auf Einschränkungen ableitet, die durch "
"Variablendeklarationen und Verwendungen gegeben sind.\n"
" \n"
"Es ist sehr wichtig zu betonen, dass auf diese Weise deklarierte Variablen nicht von einer Art "
"dynamischem \"beliebigen Typ\" sind, der dies kann\n"
"irgendwelche Daten halten. Der durch eine solche Deklaration erzeugte Maschinencode ist identisch "
@ -4706,12 +4698,15 @@ msgstr ""
#, fuzzy
msgid ""
"Notes on stack returns:\n"
msgstr ""
"Hinweise zur Stapelrückgabe:\n"
msgid ""
"* Demonstrate that the return from `add` is cheap because the compiler can eliminate the copy "
"operation. Change the above code to print stack addresses and run it on the [Playground]. In the "
"\"DEBUG\" optimization level, the addresses should change, while the stay the same when changing "
"to the \"RELEASE\" setting:"
msgstr ""
"Hinweise zur Stapelrückgabe:\n"
"* Zeigen Sie, dass die Rückgabe von `add` billig ist, weil der Compiler den Kopiervorgang "
"eliminieren kann. Ändern Sie den obigen Code, um Stapeladressen zu drucken, und führen Sie ihn auf "
"dem [Playground] aus. In der Optimierungsstufe „DEBUG“ sollen sich die Adressen ändern, während "
@ -4731,18 +4726,11 @@ msgid ""
" println!(\"&p.0: {:p}\", &p.0);\n"
" p\n"
" }"
" ```\n"
msgstr ""
#: src/ownership/borrowing.md:40
msgid ""
" fn main() {\n"
" let p1 = Point(3, 4);\n"
" let p2 = Point(10, 20);\n"
" let p3 = add(&p1, &p2);\n"
" println!(\"&p3.0: {:p}\", &p3.0);\n"
" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n"
" }\n"
" ```\n"
"* The Rust compiler can do return value optimization (RVO).\n"
"* In C++, copy elision has to be defined in the language specification because constructors can "
"have side effects. In Rust, this is not an issue at all. If RVO did not happen, Rust will always "
@ -5244,12 +5232,8 @@ msgstr ""
#: src/exercises/day-1/book-library.md:99
#, fuzzy
msgid ""
"<details>\n"
" \n"
"[Solution](solutions-afternoon.md#designing-a-library)"
msgstr ""
"<Details>\n"
" \n"
"[Lösung](solutions-afternoon.md#designing-a-library)"
#: src/exercises/day-1/iterators-and-ownership.md:1
@ -5565,10 +5549,8 @@ msgstr ""
#: src/structs.md:29
#, fuzzy
msgid ""
"<details>\n"
"Key Points: "
msgstr ""
"<Details>\n"
"Wichtige Punkte:"
#: src/structs.md:32
@ -5659,14 +5641,17 @@ msgstr ""
msgid ""
"Newtypes are a great way to encode additional information about the value in a primitive type, for "
"example:\n"
msgstr ""
"Newtypes sind eine großartige Möglichkeit, zusätzliche Informationen über den Wert in einem "
"primitiven Typ zu codieren, zum Beispiel:\n"
msgid ""
" * The number is measured in some units: `Newtons` in the example above.\n"
" * The value passed some validation when it was created, so you no longer have to validate it "
"again at every use: 'PhoneNumber(String)` or `OddNumber(u32)`.\n"
" \n"
"</details>"
msgstr ""
"Newtypes sind eine großartige Möglichkeit, zusätzliche Informationen über den Wert in einem "
"primitiven Typ zu codieren, zum Beispiel:\n"
" * Die Zahl wird in einigen Einheiten gemessen: „Newton“ im obigen Beispiel.\n"
" * Der Wert hat bei seiner Erstellung einige Validierungen durchlaufen, sodass Sie ihn nicht mehr "
"bei jeder Verwendung erneut validieren müssen: 'PhoneNumber(String)' oder 'OddNumber(u32)'.\n"
@ -5803,12 +5788,8 @@ msgstr ""
#: src/enums.md:31
#, fuzzy
msgid ""
"<details>\n"
" \n"
"Key Points:"
msgstr ""
"<Details>\n"
" \n"
"Wichtige Punkte:"
#: src/enums.md:35
@ -5994,9 +5975,6 @@ msgstr "* Siehe die [Rust-Referenz] (https://doc.rust-lang.org/reference/type-la
#: src/enums/sizes.md:39
#, fuzzy
msgid ""
"<details>\n"
" \n"
"Key Points: \n"
" * Internally Rust is using a field (discriminant) to keep track of the enum variant.\n"
" * `Bar` enum demonstrates that there is a way to control the discriminant value and type. If "
"`repr` is removed, the discriminant type takes 2 bytes, becuase 10001 fits 2 bytes.\n"
@ -6008,9 +5986,6 @@ msgid ""
" * Zero-sized types allow for efficient implementation of `HashSet` using `HashMap` with `()` as "
"the value."
msgstr ""
"<Details>\n"
" \n"
"Wichtige Punkte:\n"
" * Rust verwendet intern ein Feld (Discriminant), um die Enum-Variante zu verfolgen.\n"
" * `Bar` enum demonstriert, dass es eine Möglichkeit gibt, den Diskriminanzwert und -typ zu "
"steuern. Wenn \"repr\" entfernt wird, nimmt der Diskriminantentyp 2 Bytes ein, da 10001 auf 2 "
@ -6056,7 +6031,6 @@ msgstr ""
#: src/methods.md:30
#, fuzzy
msgid ""
"Key Points:\n"
"* It can be helpful to introduce methods by comparing them to functions.\n"
" * Methods are called on an instance of a type (such as a struct or enum), the first parameter "
"represents the instance as `self`.\n"
@ -6076,7 +6050,6 @@ msgid ""
" \n"
"</details>"
msgstr ""
"Wichtige Punkte:\n"
"* Es kann hilfreich sein, Methoden einzuführen, indem man sie mit Funktionen vergleicht.\n"
" * Methoden werden für eine Instanz eines Typs aufgerufen (z. B. eine Struktur oder Aufzählung), "
"der erste Parameter repräsentiert die Instanz als „self“.\n"
@ -6153,8 +6126,6 @@ msgstr ""
#: src/methods/receiver.md:23
#, fuzzy
msgid ""
"<details>\n"
" \n"
"Consider emphasizing on \"shared and immutable\" and \"unique and mutable\". These constraints "
"always come\n"
"together in Rust due to borrow checker rules, and `self` is no exception. It won't be possible to\n"
@ -6162,8 +6133,6 @@ msgid ""
" \n"
"</details>"
msgstr ""
"<Details>\n"
" \n"
"Erwägen Sie, die Betonung auf „gemeinsam und unveränderlich“ und „einzigartig und veränderlich“ zu "
"legen. Diese Einschränkungen kommen immer\n"
"zusammen in Rust aufgrund der Borrow-Checker-Regeln, und `self` ist keine Ausnahme. Es wird nicht "
@ -6245,9 +6214,6 @@ msgstr ""
#: src/methods/example.md:44
#, fuzzy
msgid ""
"<details>\n"
" \n"
"Key Points:\n"
"* All four methods here use a different method receiver.\n"
" * You can point out how that changes what the function can do with the variable values and if/"
"how it can be used again in `main`.\n"
@ -6259,9 +6225,6 @@ msgid ""
"* You might point out that `print_laps` is using a vector that is iterated over. We describe "
"vectors in more detail in the afternoon. "
msgstr ""
"<Details>\n"
" \n"
"Wichtige Punkte:\n"
"* Alle vier Methoden hier verwenden einen anderen Methodenempfänger.\n"
" * Sie können darauf hinweisen, wie sich das ändert, was die Funktion mit den Variablenwerten "
"machen kann und ob/wie sie wieder in `main` verwendet werden kann.\n"
@ -6320,9 +6283,6 @@ msgstr "Das `_`-Muster ist ein Platzhaltermuster, das jedem Wert entspricht."
#: src/pattern-matching.md:23
#, fuzzy
msgid ""
"<details>\n"
" \n"
"Key Points:\n"
"* You might point out how some specific characters are being used when in a pattern\n"
" * `|` as an `or`\n"
" * `..` can expand as much as it needs to be\n"
@ -6336,9 +6296,6 @@ msgid ""
" \n"
"</details>"
msgstr ""
"<Details>\n"
" \n"
"Wichtige Punkte:\n"
"* Sie können darauf hinweisen, wie bestimmte Zeichen in einem Muster verwendet werden\n"
" * `|` als `oder`\n"
" * `..` kann beliebig erweitert werden\n"
@ -6420,13 +6377,11 @@ msgstr ""
#: src/pattern-matching/destructuring-enums.md:35
#, fuzzy
msgid ""
"Key points:\n"
"* The `if`/`else` expression is returning an enum that is later unpacked with a `match`.\n"
"* You can try adding a third variant to the enum definition and displaying the errors when running "
"the code. Point out the places where your code is now inexhaustive and how the compiler trys to "
"give you hints."
msgstr ""
"Kernpunkte:\n"
"* Der `if`/`else`-Ausdruck gibt eine Aufzählung zurück, die später mit einem `match` entpackt "
"wird.\n"
"* Sie können versuchen, der Enum-Definition eine dritte Variante hinzuzufügen und die Fehler beim "
@ -6527,7 +6482,6 @@ msgstr ""
#: src/pattern-matching/match-guards.md:22
#, fuzzy
msgid ""
"Key Points:\n"
"* Match guards as a separate syntax feature are important and necessary.\n"
"* They are not the same as separate `if` expression inside of the match arm. An `if` expression "
"inside of the branch block (after `=>`) happens after the match arm is selected. Failing the `if` "
@ -6537,7 +6491,6 @@ msgid ""
"* The condition defined in the guard applies to every expression in a pattern with an `|`.\n"
"</details>"
msgstr ""
"Wichtige Punkte:\n"
"* Match Guards als separates Syntax-Feature sind wichtig und notwendig.\n"
"* Sie sind nicht dasselbe wie ein separater „if“-Ausdruck innerhalb des Match-Arms. Ein „if“-"
"Ausdruck innerhalb des Verzweigungsblocks (nach „=>“) erfolgt, nachdem der Match-Arm ausgewählt "
@ -6950,13 +6903,15 @@ msgstr ""
#, fuzzy
msgid ""
"Other interesting parts of the exercise:\n"
" \n"
msgstr ""
"Weitere interessante Teile der Übung:\n"
msgid ""
"* Derive a `Copy` trait for some structs, as in tests the methods sometimes don't borrow their "
"arguments.\n"
"* Discover that `Add` trait must be implemented for two objects to be addable via \"+\". "
msgstr ""
"Weitere interessante Teile der Übung:\n"
" \n"
"* Leiten Sie ein `Copy`-Merkmal für einige Strukturen ab, da die Methoden in Tests ihre Argumente "
"manchmal nicht ausleihen.\n"
"* Entdecken Sie, dass die Eigenschaft „Hinzufügen“ implementiert werden muss, damit zwei Objekte "
@ -7048,14 +7003,12 @@ msgstr ""
#: src/control-flow/blocks.md:42
#, fuzzy
msgid ""
"Key Points:\n"
"* The point of this slide is to show that blocks have a type and value in Rust. \n"
"* You can show how the value of the block changes by changing the last line in the block. For "
"instance, adding/removing a semicolon or using a `return`.\n"
" \n"
"</details>"
msgstr ""
"Wichtige Punkte:\n"
"* Der Zweck dieser Folie ist es zu zeigen, dass Blöcke in Rust einen Typ und einen Wert haben.\n"
"* Sie können zeigen, wie sich der Wert des Blocks ändert, indem Sie die letzte Zeile im Block "
"ändern. Zum Beispiel das Hinzufügen/Entfernen eines Semikolons oder die Verwendung eines "
@ -7294,16 +7247,12 @@ msgstr "Sie können hier wie gewohnt `break` und `continue` verwenden."
#: src/control-flow/for-expressions.md:22
#, fuzzy
msgid ""
"<details>\n"
" \n"
"* Index iteration is not a special syntax in Rust for just that case.\n"
"* `(0..10)` is a range that implements an `Iterator` trait. \n"
"* `step_by` is a method that returns another `Iterator` that skips every other element. \n"
" \n"
"</details>"
msgstr ""
"<Details>\n"
" \n"
"* Index-Iteration ist in Rust keine spezielle Syntax für genau diesen Fall.\n"
"* „(0..10)“ ist ein Bereich, der ein „Iterator“-Merkmal implementiert.\n"
"* „step_by“ ist eine Methode, die einen weiteren „Iterator“ zurückgibt, der jedes andere Element "
@ -7495,16 +7444,12 @@ msgstr ""
#: src/std.md:23
#, fuzzy
msgid ""
"<details>\n"
" \n"
" * In fact, Rust contains several layers of the Standard Library: `core`, `alloc` and `std`. \n"
" * `core` includes the most basic types and functions that don't depend on `libc`, allocator or\n"
" even the presence of an operating system. \n"
" * `alloc` includes types which require a global heap allocator, such as `Vec`, `Box` and `Arc`.\n"
" * Embedded Rust applications often only use `core`, and sometimes `alloc`."
msgstr ""
"<Details>\n"
" \n"
" * Tatsächlich enthält Rust mehrere Schichten der Standardbibliothek: `core`, `alloc` und `std`.\n"
" * `core` enthält die grundlegendsten Typen und Funktionen, die nicht von `libc`, allocator oder "
"abhängen\n"
@ -7673,8 +7618,6 @@ msgstr ""
#: src/std/vec.md:24
msgid ""
"<details>\n"
" \n"
"* `Vec` is a type of collection, along with `String` and `HashMap`. The data it contains is "
"stored\n"
" on the heap. This means the amount of data doesn't need to be known at compile time. It can "
@ -7850,29 +7793,22 @@ msgstr ""
#: src/std/box-recursive.md:33
#, fuzzy
msgid ""
"<details>\n"
" \n"
"If the `Box` was not used here and we attempted to embed a `List` directly into the `List`,\n"
"the compiler would not compute a fixed size of the struct in memory, it would look infinite.\n"
" \n"
msgstr ""
"`Box` löst dieses Problem, da es die gleiche Größe wie ein normaler Zeiger hat und nur auf den "
"nächsten zeigt\n"
"Element der `Liste` im Heap.\n"
msgid ""
"`Box` solves this problem as it has the same size as a regular pointer and just points at the "
"next\n"
"element of the `List` in the heap. \n"
" \n"
"</details>"
msgstr ""
"<Details>\n"
" \n"
"Wenn die `Box` hier nicht verwendet wurde und wir versucht haben, eine `List` direkt in die `List` "
"einzubetten,\n"
"Der Compiler würde keine feste Größe der Struktur im Speicher berechnen, es würde unendlich "
"aussehen.\n"
" \n"
"`Box` löst dieses Problem, da es die gleiche Größe wie ein normaler Zeiger hat und nur auf den "
"nächsten zeigt\n"
"Element der `Liste` im Heap.\n"
" \n"
"</details>"
#: src/std/box-niche.md:1
#, fuzzy
@ -8525,12 +8461,6 @@ msgstr ""
#: src/traits.md:46
msgid ""
"Compare these outputs in the above example:\n"
"```rust,ignore\n"
" println!(\"{} {}\", std::mem::size_of::<Dog>(), std::mem::size_of::<Cat>());\n"
" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n"
" println!(\"{}\", std::mem::size_of::<&dyn Greet>());\n"
" println!(\"{}\", std::mem::size_of::<Box<dyn Greet>>());\n"
"```"
msgstr ""
#: src/traits/deriving-traits.md:1
@ -8805,8 +8735,6 @@ msgstr ""
#: src/traits/from-into.md:27
#, fuzzy
msgid ""
"<details>\n"
" \n"
"* That's why it is common to only implement `From`, as your type will get `Into` implementation "
"too.\n"
"* When declaring a function argument input type like \"anything that can be converted into a "
@ -8815,8 +8743,6 @@ msgid ""
" \n"
"</details>"
msgstr ""
"<Details>\n"
" \n"
"* Aus diesem Grund ist es üblich, nur `From` zu implementieren, da Ihr Typ auch die `Into`-"
"Implementierung erhält.\n"
"* Beim Deklarieren eines Funktionsargument-Eingabetyps wie „alles, was in einen „String“ "
@ -9184,8 +9110,6 @@ msgstr ""
#: src/generics/trait-bounds.md:22
msgid ""
"Show a `where` clause, students will encounter it when reading code.\n"
" \n"
"```rust,ignore\n"
"fn duplicate<T>(a: T) -> (T, T)\n"
"where\n"
@ -11675,8 +11599,6 @@ msgstr "[1]: https://doc.rust-lang.org/std/thread/fn.scope.html"
#: src/concurrency/scoped-threads.md:35
#, fuzzy
msgid ""
"<details>\n"
" \n"
"* The reason for that is that when the `thread::scope` function completes, all the threads are "
"guaranteed to be joined, so they can return borrowed data.\n"
"* Normal Rust borrowing rules apply: you can either borrow mutably by one thread, or immutably by "
@ -11684,8 +11606,6 @@ msgid ""
" \n"
"</details>"
msgstr ""
"<Details>\n"
" \n"
"* Der Grund dafür ist, dass nach Abschluss der `thread::scope`-Funktion garantiert alle Threads "
"verbunden sind, sodass sie geliehene Daten zurückgeben können.\n"
"* Es gelten die normalen Rust-Ausleihregeln: Sie können entweder veränderlich von einem Thread "
@ -11988,8 +11908,6 @@ msgstr ""
#: src/concurrency/shared_state/mutex.md:30
#, fuzzy
msgid ""
"<details>\n"
" \n"
"* `Mutex` in Rust looks like a collection with just one element - the protected data.\n"
" * It is not possible to forget to acquire the mutex before accessing the protected data.\n"
"* You can get an `&mut T` from an `&Mutex<T>` by taking the lock. The `MutexGuard` ensures that "
@ -12005,8 +11923,6 @@ msgid ""
" fails with a [`PoisonError`]. You can call `into_inner()` on the error to recover the data\n"
" regardless."
msgstr ""
"<Details>\n"
" \n"
"* `Mutex` in Rust sieht aus wie eine Sammlung mit nur einem Element - den geschützten Daten.\n"
" * Es ist nicht möglich, das Abrufen des Mutex zu vergessen, bevor auf die geschützten Daten "
"zugegriffen wird.\n"
@ -12068,14 +11984,11 @@ msgstr ""
#: src/concurrency/shared_state/example.md:23
msgid ""
"Possible solution:\n"
" \n"
"```rust,editable\n"
"use std::sync::{Arc, Mutex};\n"
"use std::thread;"
msgstr ""
#: src/concurrency/shared_state/example.md:29
msgid ""
"```rust,editable\n"
"fn main() {\n"
" let v = Arc::new(Mutex::new(vec![10, 20, 30]));"
msgstr ""
@ -12099,17 +12012,11 @@ msgstr ""
#: src/concurrency/shared_state/example.md:43
msgid " handle.join().unwrap();"
"```\n"
msgstr ""
#: src/concurrency/shared_state/example.md:45
msgid ""
" {\n"
" let v = v.lock().unwrap();\n"
" println!(\"v: {v:?}\");\n"
" }\n"
"}\n"
"```\n"
" \n"
"Notable parts:"
msgstr ""
@ -14556,8 +14463,9 @@ msgid ""
" println!(\"transposed:\");\n"
" pretty_print(&transposed);\n"
"}\n"
"```\n"
"### Bonus question"
msgstr ""
msgid "### Bonus question"
msgstr ""
#: src/exercises/day-1/solutions-morning.md:80

361
po/ko.po
View File

@ -929,54 +929,6 @@ msgid ""
"cover as well as answers to typical questions which come up in class."
msgstr "이것은 \"발표자 노트\"의 예제입니다. 이 부분을 이용해서 추가 정보를 제공합니다. 주로 강의실에서 제기되는 일반적인 질문에 대한 답변과 강사가 다루어야 할 키 포인트일 수 있습니다."
#: src/welcome.md:52 src/cargo/rust-ecosystem.md:67
#: src/cargo/code-samples.md:35 src/cargo/running-locally.md:74
#: src/welcome-day-1.md:42 src/welcome-day-1/what-is-rust.md:29
#: src/hello-world.md:36 src/hello-world/small-example.md:44 src/why-rust.md:24
#: src/why-rust/compile-time.md:35 src/why-rust/runtime.md:22
#: src/why-rust/modern.md:66 src/basic-syntax/compound-types.md:62
#: src/basic-syntax/references.md:28 src/basic-syntax/slices.md:36
#: src/basic-syntax/functions.md:54 src/exercises/day-1/morning.md:28
#: src/exercises/day-1/for-loops.md:95 src/basic-syntax/variables.md:20
#: src/basic-syntax/type-inference.md:48
#: src/basic-syntax/static-and-const.md:52
#: src/basic-syntax/scopes-shadowing.md:39 src/memory-management/stack.md:49
#: src/memory-management/rust.md:18 src/ownership/move-semantics.md:26
#: src/ownership/moves-function-calls.md:26 src/ownership/borrowing.md:51
#: src/ownership/shared-unique-borrows.md:29
#: src/ownership/lifetimes-function-calls.md:60
#: src/exercises/day-1/afternoon.md:15 src/exercises/day-1/book-library.md:106
#: src/structs.md:41 src/structs/field-shorthand.md:41 src/enums/sizes.md:155
#: src/methods/example.md:53 src/pattern-matching/destructuring-enums.md:39
#: src/pattern-matching/destructuring-arrays.md:46
#: src/exercises/day-2/morning.md:15 src/exercises/day-2/points-polygons.md:125
#: src/control-flow/if-let-expressions.md:26
#: src/control-flow/for-expressions.md:29
#: src/control-flow/loop-expressions.md:27 src/std.md:31
#: src/std/option-result.md:25 src/std/string.md:40 src/std/vec.md:49
#: src/std/hashmap.md:66 src/std/rc.md:69 src/modules.md:32
#: src/modules/visibility.md:48 src/modules/filesystem.md:53
#: src/exercises/day-2/afternoon.md:11 src/traits.md:54
#: src/traits/from-iterator.md:26 src/traits/operators.md:38
#: src/traits/drop.md:42 src/traits/default.md:47 src/generics/methods.md:31
#: src/generics/closures.md:38 src/exercises/day-3/morning.md:11
#: src/error-handling/try-operator.md:55
#: src/error-handling/converting-error-types-example.md:60
#: src/error-handling/deriving-error-enums.md:45
#: src/error-handling/dynamic-errors.md:41
#: src/error-handling/error-contexts.md:42 src/unsafe.md:32
#: src/unsafe/raw-pointers.md:42 src/unsafe/mutable-static-variables.md:35
#: src/unsafe/unions.md:28 src/unsafe/writing-unsafe-functions.md:38
#: src/unsafe/extern-functions.md:28 src/unsafe/unsafe-traits.md:37
#: src/exercises/day-3/afternoon.md:11 src/concurrency/threads.md:45
#: src/concurrency/channels.md:32 src/concurrency/shared_state/arc.md:38
#: src/concurrency/shared_state/example.md:60
#: src/concurrency/send-sync/sync.md:18 src/exercises/day-4/morning.md:16
#: src/android/interoperability/with-c/rust.md:86
#: src/exercises/day-4/afternoon.md:15
msgid "</details>"
msgstr "</details>"
#: src/running-the-course.md:1
msgid "# Running the Course"
msgstr "# 강의 진행 방식"
@ -2480,14 +2432,11 @@ msgid ""
"* For C++ programmers: think of `&str` as `const char*` from C++, but the one that always points \n"
" to a valid string in memory. Rust `String` is a rough equivalent of `std::string` from C++ \n"
" (main difference: it can only contain UTF-8 encoded bytes and will never use a small-string optimization).\n"
" \n"
"</details>"
msgstr ""
"* `format!()` 매크로는 변수의 값을 문자열로 변환하는 편리한 방법입니다. 이 매크로는 `println!()` 매크로와 동일한 포맷팅 형식을 지원합니다.\n"
"* `&`와 범위 연산자를 이용하여 `String`에서 `&str`슬라이스를 빌려올 수 있습니다.\n"
"* 당신이 C++ 프로그래머 라면: `&str`는 C++의 `const char*`와 유사하지만 항상 유효한 문자열을 가리킨다는 점이 다릅니다. 러스트의 `String`은 C++의 `std::string` 과 대략 거의 동일합니다. (주요 차이점: 러스트의 `String`은 UTF-8 인코딩 바이트만 포함할 수 있으며 작은 문자열 최적화(small-string optimization)는 사용하지 않습니다.\n"
" \n"
"</details>"
#: src/basic-syntax/functions.md:1
msgid "# Functions"
@ -3070,6 +3019,11 @@ msgstr ""
msgid ""
"This slide demonstrates how the Rust compiler infers types based on constraints given by variable declarations and usages.\n"
" \n"
msgstr ""
"이 슬라이드는, 러스트 컴파일러가 변수가 어떻게 선언되어 있고, 어떻게 사용되는지를 제약 조건으로 삼아서 변수의 타입을 추론하는 모습을 보여줍니다.\n"
" \n"
msgid ""
"It is very important to emphasize that variables declared like this are not of some sort of dynamic \"any type\" that can\n"
"hold any data. The machine code generated by such declaration is identical to the explicit declaration of a type.\n"
"The compiler does the job for us and helps us write more concise code."
@ -4060,9 +4014,12 @@ msgstr ""
#: src/ownership/borrowing.md:27
msgid ""
"Notes on stack returns:\n"
"* Demonstrate that the return from `add` is cheap because the compiler can eliminate the copy operation. Change the above code to print stack addresses and run it on the [Playground]. In the \"DEBUG\" optimization level, the addresses should change, while the stay the same when changing to the \"RELEASE\" setting:"
msgstr ""
"스택에 할당된 값을 리턴하는 것에 대한 참고: \n"
msgid ""
"* Demonstrate that the return from `add` is cheap because the compiler can eliminate the copy operation. Change the above code to print stack addresses and run it on the [Playground]. In the \"DEBUG\" optimization level, the addresses should change, while the stay the same when changing to the \"RELEASE\" setting:"
msgstr ""
"* `add`에서 값을 반환하는 것은 매우 값이 싸다는 것을 설명하세요. 왜냐하면, 컴파일러가 복사 과정을 생략할 수 있기 때문입니다. 위 코드를 스택 주소를 출력하도록 수정하고 [Playground]에서 수행해 보세요. \"디버그\" 최적화 레벨에서는 주소가 바뀌지만, \"릴리즈\" 레벨에서는 바뀌지 않습니다:"
#: src/ownership/borrowing.md:30
@ -4091,8 +4048,6 @@ msgid ""
" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n"
" }\n"
" ```\n"
"* The Rust compiler can do return value optimization (RVO).\n"
"* In C++, copy elision has to be defined in the language specification because constructors can have side effects. In Rust, this is not an issue at all. If RVO did not happen, Rust will always performs a simple and efficient `memcpy` copy."
msgstr ""
" fn main() {\n"
" let p1 = Point(3, 4);\n"
@ -4102,6 +4057,11 @@ msgstr ""
" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n"
" }\n"
" ```\n"
msgid ""
"* The Rust compiler can do return value optimization (RVO).\n"
"* In C++, copy elision has to be defined in the language specification because constructors can have side effects. In Rust, this is not an issue at all. If RVO did not happen, Rust will always performs a simple and efficient `memcpy` copy."
msgstr ""
"* 러스트 컴파일러는 반환값 최적화(RVO)를 수행할 수 있습니다.\n"
"* C++에서 copy elision은 생성자의 부수효과 가능성이 있어 언어레벨의 정의가 필요하지만 러스트에서는 문제가 되지 않습니다. 만약 RVO가 발생하지 않으면 러스트는 항상 간단하고 효율적인 `memcpy`복사를 수행할 것입니다."
@ -4245,28 +4205,8 @@ msgstr ""
#: src/ownership/lifetimes-function-calls.md:40
msgid ""
" fn main() {\n"
" let p1: Point = Point(10, 10);\n"
" let p3: &Point;\n"
" {\n"
" let p2: Point = Point(20, 20);\n"
" p3 = left_most(&p1, &p2);\n"
" }\n"
" println!(\"left-most point: {:?}\", p3);\n"
" }\n"
" ```\n"
" Note how this does not compile since `p3` outlives `p2`."
msgstr ""
" fn main() {\n"
" let p1: Point = Point(10, 10);\n"
" let p3: &Point;\n"
" {\n"
" let p2: Point = Point(20, 20);\n"
" p3 = left_most(&p1, &p2);\n"
" }\n"
" println!(\"left-most point: {:?}\", p3);\n"
" }\n"
" ```\n"
" `p3`의 수명이 `p2` 보다 길기 때문에 이 예제는 컴파일되지 않음을 확인하시기 바랍니다."
#: src/ownership/lifetimes-function-calls.md:52
@ -4532,12 +4472,8 @@ msgstr ""
#: src/exercises/day-1/book-library.md:102
msgid ""
"<details>\n"
" \n"
"[Solution](solutions-afternoon.md#designing-a-library)"
msgstr ""
"<details>\n"
" \n"
"[해답](solutions-afternoon.md#designing-a-library)"
#: src/exercises/day-1/iterators-and-ownership.md:1
@ -5016,12 +4952,8 @@ msgstr ""
#: src/enums.md:31 src/enums/sizes.md:27
msgid ""
"<details>\n"
" \n"
"Key Points:"
msgstr ""
"<details>\n"
" \n"
"키 포인트:"
#: src/enums.md:35
@ -5177,9 +5109,26 @@ msgstr ""
msgid "* See the [Rust Reference](https://doc.rust-lang.org/reference/type-layout.html)."
msgstr "* 자세한 사항은 [공식문서](https://doc.rust-lang.org/reference/type-layout.html)를 확인하세요."
#: src/enums/sizes.md:31
msgid " * Internally Rust is using a field (discriminant) to keep track of the enum variant."
msgstr "* 러스트는 열거형 variant를 구분하기 위해 내부적으로 식별자(discriminant) 필드를 사용합니다."
#: src/enums/sizes.md:39
msgid ""
"Key Points: \n"
msgstr ""
"키 포인트: \n"
msgid ""
" * Internally Rust is using a field (discriminant) to keep track of the enum variant.\n"
" * `Bar` enum demonstrates that there is a way to control the discriminant value and type. If `repr` is removed, the discriminant type takes 2 bytes, becuase 10001 fits 2 bytes.\n"
" * As a niche optimization an enum discriminant is merged with the pointer so that `Option<&Foo>` is the same size as `&Foo`.\n"
" * `Option<bool>` is another example of tight packing.\n"
" * For [some types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees that `size_of::<T>()` equals `size_of::<Option<T>>()`.\n"
" * Zero-sized types allow for efficient implementation of `HashSet` using `HashMap` with `()` as the value."
msgstr ""
"* 러스트는 열거형 variant를 구분하기 위해 내부적으로 식별자(discriminant) 필드를 사용합니다."
"* `Bar` 타입을 보면 식별자의 값을 직접 지정하거나 그 타입을 변경할 수 있음을 알 수 있습니다.`repr`을 제거하면 10001을 나타내는데 2바이트가 필요하기 때문에 식별자 타입이 2바이트를 차지합니다.\n"
"* 니치 최적화(niche optimization)로서 열거형(enum)의 식별자는 포인터에 결합됩니다.그래서 `Option<&Foo>` 타입은 `&Foo`와 같은 사이즈가 됩니다.\n"
"* `Option<bool>역시 이에 대한 또 다른 예입니다.\n"
"* [일부 타입](https://doc.rust-lang.org/std/option/#representation)의 경우 러스트는 `size_of::<T>()`와 `size_of::<Option<T>>()`가 동일함을 보장합니다. \n"
"* 0크기 타입 덕분에 `HashMap`의 값을 `()`로 지정하는 식으로 `HashSet`을 효율적으로 구현할 수 있습니다."
#: src/enums/sizes.md:33
msgid ""
@ -5468,6 +5417,10 @@ msgstr ""
#: src/methods.md:30
msgid ""
"Key Points:\n"
msgstr ""
"키 포인트: \n"
msgid ""
"* It can be helpful to introduce methods by comparing them to functions.\n"
" * Methods are called on an instance of a type (such as a struct or enum), the first parameter represents the instance as `self`.\n"
" * Developers may choose to use methods to take advantage of method receiver syntax and to help keep them more organized. By using methods we can keep all the implementation code in one predictable place.\n"
@ -5477,10 +5430,7 @@ msgid ""
" * Note how `self` is used like other structs and dot notation can be used to refer to individual fields.\n"
" * This might be a good time to demonstrate how the `&self` differs from `self` by modifying the code and trying to run say_hello twice. \n"
"* We describe the distinction between method receivers next.\n"
" \n"
"</details>"
msgstr ""
"키 포인트: \n"
"* 메서드를 함수와 비교하여 소개하는 것도 도움이 될 수 있습니다.\n"
" * 메서드는 구조체나 열거형과 같은 타입의 인스턴스에서 호출 되며, 첫번째 매개변수(파라메터)는 인스턴스를 `self`로 표기합니다.\n"
" * 메서드를 이용하면 receiver 문법을 사용할 수 있고 코드를 좀더 체계적으로 정리할 수 있습니다. 메서드들이 예측 가능한 위치에 모여 있으니 찾기 쉽습니다.\n"
@ -5490,7 +5440,6 @@ msgstr ""
" * 구조체의 필드를 접근할 때 점 표기를 사용하듯이 `self`에 점 표기를 사용하여 개별 필드들을 접근할 수 있습니다.\n"
" * `say_hello` 함수가 두 번 호출되도록 코드를 수정하여 `&self`와 `self`가 어떻게 다른지 보여주는 것도 좋습니다.\n"
"* 다음 슬라이드에서 receiver의 구분을 설명합니다.\n"
"</details>"
#: src/methods/receiver.md:1
msgid "# Method Receiver"
@ -5532,16 +5481,12 @@ msgstr "`self`를 사용하는 이같은 변형들 외에도 `Box<Self>`와 같
#: src/methods/receiver.md:23
msgid ""
"<details>\n"
" \n"
"Consider emphasizing \"shared and immutable\" and \"unique and mutable\". These constraints always come\n"
"together in Rust due to borrow checker rules, and `self` is no exception. It isn't possible to\n"
"reference a struct from multiple locations and call a mutating (`&mut self`) method on it.\n"
" \n"
"</details>"
msgstr ""
"<details>\n"
" \n"
" \"공유가능한 불변\"과 \"유일한 가변\" 부분은 강조할 만합니다. 이러한 제약은 러스트의 빌림 검사기(borrow checker) 규칙으로 늘 붙어다닙니다. `self`도 예외는 아닙니다. 여러 위치에서 구조체를 참조하면서 객체를 수정하는(`&mut self`를 리시버로 하는) 메서드를 호출하는 것은 불가능합니다.\n"
"</details>"
@ -5628,17 +5573,12 @@ msgstr ""
#: src/methods/example.md:44
msgid ""
"<details>\n"
" \n"
"Key Points:\n"
"* All four methods here use a different method receiver.\n"
" * You can point out how that changes what the function can do with the variable values and if/how it can be used again in `main`.\n"
" * You can showcase the error that appears when trying to call `finish` twice.\n"
"* Note that although the method receivers are different, the non-static functions are called the same way in the main body. Rust enables automatic referencing and dereferencing when calling methods. Rust automatically adds in the `&`, `*`, `muts` so that that object matches the method signature.\n"
"* You might point out that `print_laps` is using a vector that is iterated over. We describe vectors in more detail in the afternoon. "
msgstr ""
"<details>\n"
" \n"
"키 포인트:\n"
"* 4가지 유형의 메서드 receiver에 대해 설명합니다.\n"
" * receiver 유형에 따라 함수가 할 수 있는 일이 달라지고, 또 메소드를 호출한 뒤 `main`에서 해당 객체를 사용할 수 있는지 여부도 달라진다는 점을 강조하세요.\n"
@ -5685,9 +5625,6 @@ msgstr "`_`패턴은 어떤 값과도 매칭되는 와일드카드입니다."
#: src/pattern-matching.md:23
msgid ""
"<details>\n"
" \n"
"Key Points:\n"
"* You might point out how some specific characters are being used when in a pattern\n"
" * `|` as an `or`\n"
" * `..` can expand as much as it needs to be\n"
@ -5696,12 +5633,7 @@ msgid ""
"* It can be useful to show how binding works, by for instance replacing a wildcard character with a variable, or removing the quotes around `q`.\n"
"* You can demonstrate matching on a reference.\n"
"* This might be a good time to bring up the concept of irrefutable patterns, as the term can show up in error messages.\n"
" \n"
"</details>"
msgstr ""
"<details>\n"
" \n"
"키 포인트:\n"
"* 패턴에서 사용되는 특수 문자들을 알려주세요.\n"
" * `|`: or 기호입니다.\n"
" * `..`: 필요한 만큼 확장합니다.\n"
@ -5710,8 +5642,6 @@ msgstr ""
"* 와일드카드 문자를 변수로 바꾸거나 `q`의 따옴표를 제거하는 식으로 수정하면서 바인딩이 어떻게 작동하는지 보여주는 것도 유용할 수 있습니다.\n"
"* 참조를 매칭하는 것도 시연할 수 있습니다.\n"
"* 에러 메시지에 \"반박 불가능 패턴(irrefutable pattern)\"이란 용어가 등장하기도 합니다. 지금 그 의미를 소개하는 것도 좋을 것 같습니다.\n"
"\n"
"</details>"
#: src/pattern-matching/destructuring-enums.md:1
msgid "# Destructuring Enums"
@ -5784,11 +5714,9 @@ msgstr "`match`구문에서 `divide_in_two`함수에서 반환되는 `Result`
#: src/pattern-matching/destructuring-enums.md:35
msgid ""
"Key points:\n"
"* The `if`/`else` expression is returning an enum that is later unpacked with a `match`.\n"
"* You can try adding a third variant to the enum definition and displaying the errors when running the code. Point out the places where your code is now inexhaustive and how the compiler tries to give you hints."
msgstr ""
"키 포인트:\n"
"* `if`/`else` 표현식은 열거형을 반환하고, 이 값은 나중에 `match`로 분해됩니다.\n"
"* 열거형에 세번째 variant를 추가하고 코드를 실행하여 오류를 표시해보세요. 코드 어느 부분에 누락이 있는지, 그리고 컴파일러가 어떤 식으로 힌트를 주는지 같이 살펴보세요."
@ -5825,8 +5753,6 @@ msgid ""
" Foo { y, .. } => println!(\"y = {y}, other fields were ignored\"),\n"
" }\n"
"}\n"
"```\n"
"<details>"
msgstr ""
"#[rustfmt::skip]\n"
"fn main() {\n"
@ -5837,8 +5763,6 @@ msgstr ""
" Foo { y, .. } => println!(\"y = {y}, other fields were ignored\"),\n"
" }\n"
"}\n"
"```\n"
"<details>"
#: src/pattern-matching/destructuring-structs.md:23
msgid ""
@ -5906,37 +5830,9 @@ msgstr ""
#: src/pattern-matching/destructuring-arrays.md:30
msgid ""
"#[rustfmt::skip]\n"
"fn inspect(slice: &[i32]) {\n"
" println!(\"Tell me about {slice:?}\");\n"
" match slice {\n"
" &[0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n"
" &[1, ..] => println!(\"First is 1 and the rest were ignored\"),\n"
" _ => println!(\"All elements were ignored\"),\n"
" }\n"
"}\n"
"```\n"
" \n"
"* Create a new pattern using `_` to represent an element. \n"
"* Add more values to the array.\n"
"* Point out that how `..` will expand to account for different number of elements.\n"
"* Show matching against the tail with patterns `[.., b]` and `[a@..,b]`"
"* Show matching against the tail with patterns `[.., b]` and `[a@..,b]`\n"
msgstr ""
"#[rustfmt::skip]\n"
"fn inspect(slice: &[i32]) {\n"
" println!(\"Tell me about {slice:?}\");\n"
" match slice {\n"
" &[0, y, z] => println!(\"First is 0, y = {y}, and z = {z}\"),\n"
" &[1, ..] => println!(\"First is 1 and the rest were ignored\"),\n"
" _ => println!(\"All elements were ignored\"),\n"
" }\n"
"}\n"
"```\n"
"* 엘리먼트를 매칭할 때 `_`를 사용하는 패턴을 추가해 보세요.\n"
"* 배열에 값을 더 추가해 보세요.\n"
"* `..`가 서로 다른 개수의 엘리먼트들에 대해 어떻게 확장되는지 설명하세요.\n"
"* `[.., b]`나 `[a@.., b]`와 같은 패턴으로 꼬리 부분을 매칭하는 것을 보여주세요.\n"
"</details>"
#: src/pattern-matching/match-guards.md:1
msgid "# Match Guards"
@ -5980,7 +5876,6 @@ msgstr ""
#: src/pattern-matching/match-guards.md:22
msgid ""
"Key Points:\n"
"* Match guards as a separate syntax feature are important and necessary when we wish to concisely express more complex ideas than patterns alone would allow.\n"
"* They are not the same as separate `if` expression inside of the match arm. An `if` expression inside of the branch block (after `=>`) happens after the match arm is selected. Failing the `if` condition inside of that block won't result in other arms\n"
"of the original `match` expression being considered. \n"
@ -5988,7 +5883,6 @@ msgid ""
"* The condition defined in the guard applies to every expression in a pattern with an `|`.\n"
"</details>"
msgstr ""
"키 포인트:\n"
"* 매치 가드는 별도의 문법 요소로서 패턴 자체만으로 표현하기 어려운 복잡한 경우를 간결하게 표현하고자 할 때 유용합니다.\n"
"* 매치의 각 팔(혹은 가지) 안에 따로 `if`를 사용한 것과 다릅니다. 매치 가지의 `=>` 뒤에 사용된 `if` 표현식은 해당\n"
" 가지가 선택된 다음에 실행됩니다. 따라서 여기서 `if` 조건이 실패하더라도 원래 `match`의 다른 가지는 고려되지 않습니다.\n"
@ -6315,12 +6209,15 @@ msgstr "누락된 메서드 시그니처를 올바르게 정의하는 것이 문
#: src/exercises/day-2/points-polygons.md:120
msgid ""
"Other interesting parts of the exercise:\n"
" \n"
"* Derive a `Copy` trait for some structs, as in tests the methods sometimes don't borrow their arguments.\n"
"* Discover that `Add` trait must be implemented for two objects to be addable via \"+\". Note that we do not discuss generics until Day 3."
msgstr ""
"연습문제의 다른 흥미로운 부분:\n"
" \n"
#: src/exercises/day-2/points-polygons.md:121
msgid ""
"* Derive a `Copy` trait for some structs, as in tests the methods sometimes don't borrow their arguments.\n"
"* Discover that `Add` trait must be implemented for two objects to be addable via \"+\". Note that we do not discuss generics until Day 3."
msgstr ""
"* 테스트 코드를 보면 어떤 메서드들은 인자를 borrow하는 대신 `Copy` 트레잇을 사용하기도 합니다. 구조체가 `Copy` 트레잇을 상속(derive)하도록 하면 됩니다.\n"
"* \"+\"를 사용하여 두 객체를 서로 더하려면 `Add` 트레잇을 구현해야 합니다. 이는 3일차에 다룰 내용입니다."
@ -6396,17 +6293,12 @@ msgstr "위의 `main` 함수는 마지막 표현식이 `;`로 끝나기 때문
#: src/control-flow/blocks.md:42
msgid ""
"Key Points:\n"
"* The point of this slide is to show that blocks have a type and value in Rust. \n"
"* You can show how the value of the block changes by changing the last line in the block. For instance, adding/removing a semicolon or using a `return`.\n"
" \n"
"</details>"
msgstr ""
"키 포인트:\n"
"* 러스트에서는 블록이 타입과 값을 가진다는 점이 이 슬라이드의 핵심입니다.\n"
"* 블록 마지막 줄을 수정하면서 블록의 값이 어떻게 바뀌는지 보여주세요. 예를 들어, 세미콜론을\n"
" 넣거나 뺀다든지, 아니면 `return`을 사용해 보세요.\n"
"</details>"
#: src/control-flow/if-expressions.md:1
msgid "# `if` expressions"
@ -6606,15 +6498,11 @@ msgstr "다른 언어와 마찬가지로 `break` 와 `continue`를 사용할 수
#: src/control-flow/for-expressions.md:22
msgid ""
"<details>\n"
" \n"
"* Index iteration is not a special syntax in Rust for just that case.\n"
"* `(0..10)` is a range that implements an `Iterator` trait. \n"
"* `step_by` is a method that returns another `Iterator` that skips every other element. \n"
"* Modify the elements in the vector and explain the compiler errors. Change vector `v` to be mutable and the for loop to `for x in v.iter_mut()`."
msgstr ""
"<details>\n"
" \n"
"* 러스트는 인덱스 반복을 위해 별도의 문법을 사용하지 않습니다. \n"
"* `(0..10)`은 `Iterator` 트레잇을 구현하는 범위(range) 값입니다. \n"
"* `step_by`는 반복자의 요소들을 건너뛰는 또다른 `Iterator`를 반환하는 메서드입니다.\n"
@ -6652,12 +6540,8 @@ msgstr ""
#: src/control-flow/loop-expressions.md:23
msgid ""
"<details>\n"
" \n"
"* Break the `loop` with a value (e.g. `break 8`) and print it out."
msgstr ""
"<details>\n"
" \n"
"* `loop` 블록을 빠져나올 때 `break 8`처럼 값을 지정하고 그걸 출력해보세요."
#: src/control-flow/match-expressions.md:1
@ -6818,16 +6702,12 @@ msgstr "* [`Rc`](std/rc.md): 힙에 할당된 데이터에 대한 참조 카운
#: src/std.md:23
msgid ""
"<details>\n"
" \n"
" * In fact, Rust contains several layers of the Standard Library: `core`, `alloc` and `std`. \n"
" * `core` includes the most basic types and functions that don't depend on `libc`, allocator or\n"
" even the presence of an operating system. \n"
" * `alloc` includes types which require a global heap allocator, such as `Vec`, `Box` and `Arc`.\n"
" * Embedded Rust applications often only use `core`, and sometimes `alloc`."
msgstr ""
"<details>\n"
" \n"
" * 사실, 러스트의 표준 라이브러리는 `core`, `alloc`, `std`와 같이 계층(layer)으로 나눠집니다.\n"
" * `core`는 `libc`나 할당자(allocator), 심지어 OS에도 의존하지 않는 가장 기본적인 함수와 타입을 포함합니다.\n"
" * `alloc`은 `Vec`, `Box`, `Arc`와 같이 전역 힙 할당이 필요한 타입을 포함합니다.\n"
@ -8050,20 +7930,8 @@ msgstr ""
#: src/traits.md:46
msgid ""
"Compare these outputs in the above example:\n"
"```rust,ignore\n"
" println!(\"{} {}\", std::mem::size_of::<Dog>(), std::mem::size_of::<Cat>());\n"
" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n"
" println!(\"{}\", std::mem::size_of::<&dyn Greet>());\n"
" println!(\"{}\", std::mem::size_of::<Box<dyn Greet>>());\n"
"```"
msgstr ""
"위의 예제에 아래를 추가하여 출력을 비교해 보시기 바랍니다:\n"
"```rust,ignore\n"
" println!(\"{} {}\", std::mem::size_of::<Dog>(), std::mem::size_of::<Cat>());\n"
" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n"
" println!(\"{}\", std::mem::size_of::<&dyn Greet>());\n"
" println!(\"{}\", std::mem::size_of::<Box<dyn Greet>>());\n"
"```"
#: src/traits/deriving-traits.md:1
msgid "# Deriving Traits"
@ -8231,13 +8099,10 @@ msgid ""
" (e.g. `map`, `filter`, `reduce`, etc). This is the trait where you can find all the documentation\n"
" about them. In Rust these functions should produce the code as efficient as equivalent imperative\n"
" implementations.\n"
" \n"
"</details>"
msgstr ""
"* `IntoIterator`는 루프가 작동하도록 만드는 트레잇입니다. `Vec<T>`와 같은 컬렉션 타입과 그에 대한 참조 타입(`&Vec<T>`, `&[T]`)들 모두 이 트레잇을 구현합니다. Range 역시 이를 구현합니다.\n"
"* `Iterator` 트레잇은 컬렉션에 대해 다양한 함수형 프로그래밍 연산 (`map`, `filter`, `reduce` 등)을 구현합니다. 이 연산들에 대한 자세한 설명은 `Iterator` 트레잇의 API 레퍼런스에서 찾을 수 있습니다. 러스트에서 이러한 함수형 연산들은 절차형으로 구현된 코드와 동일한 성능을 보여줍니다.\n"
" \n"
"</details>"
#: src/traits/iterator.md:41
msgid "[1]: https://doc.rust-lang.org/std/iter/trait.Iterator.html"
@ -8332,20 +8197,12 @@ msgstr ""
#: src/traits/from-into.md:27
msgid ""
"<details>\n"
" \n"
"* That's why it is common to only implement `From`, as your type will get `Into` implementation too.\n"
"* When declaring a function argument input type like \"anything that can be converted into a `String`\", the rule is opposite, you should use `Into`.\n"
" Your function will accept types that implement `From` and those that _only_ implement `Into`.\n"
" \n"
"</details>"
msgstr ""
"<details>\n"
" \n"
"* 그렇기 때문에 사용자 정의 타입의 경우에도 `From` 만 구현하는 것이 일반적입니다.\n"
"* \"`String`으로 변환할 수 있는 모든 것\"과 같은 함수의 인수 타입을 선언할 때에는 `Into`를 사용해야 함을 조심하세요. 그래야만, 함수는 `From`을 구현한 타입과 `Into` _만_ 구현한 타입 모두를 인자로 받을 수 있습니다.\n"
" \n"
"</details>"
#: src/traits/from-into.md:35
msgid ""
@ -8805,39 +8662,18 @@ msgstr ""
#: src/generics/trait-bounds.md:35
msgid ""
"Show a `where` clause, students will encounter it when reading code.\n"
" \n"
"```rust,ignore\n"
"fn duplicate<T>(a: T) -> (T, T)\n"
"where\n"
" T: Clone,\n"
"{\n"
" (a.clone(), a.clone())\n"
"}\n"
"```"
msgstr ""
"`where` 문법을 사용할 수도 있습니다. 수강생들도 코드를 읽다가 그 문법을 마주할 수 있습니다.\n"
"```rust,ignore\n"
"fn duplicate<T>(a: T) -> (T, T)\n"
"where\n"
" T: Clone,\n"
"{\n"
" (a.clone(), a.clone())\n"
"}\n"
"```"
#: src/generics/trait-bounds.md:46
msgid ""
"* It declutters the function signature if you have many parameters.\n"
"* It has additional features making it more powerful.\n"
" * If someone asks, the extra feature is that the type on the left of \":\" can be arbitrary, like `Option<T>`.\n"
" \n"
"</details>"
msgstr ""
"* 이를 이용하면 타입 파라메터가 많은 경우 함수 시그니처를 간결하게 정리하는 데 도움이 됩니다.\n"
"* 좀 더 강력한 추가 기능도 제공합니다.\n"
" * `:` 왼쪽에 임의의 타입(예를 들어 `Option<T>`)을 사용할 수 있습니다.\n"
" \n"
"</details>"
#: src/generics/impl-trait.md:1
msgid "# `impl Trait`"
@ -8902,12 +8738,9 @@ msgid ""
"It would not work for this particular function, as the type we expect as input is likely not\n"
"what `format!` returns. If we wanted to do the same via `: Display` syntax, we'd need two\n"
"independent generic parameters.\n"
" \n"
"</details>"
msgstr ""
"이 예시는 `impl Display`가 두번 사용 되었다는 점에서 훌륭합니다. 여기서 중요한 것은 이 두 `impl Display`가 실제로 같은 타입일 필요가 없다는 것입니다. 만약 `T: Display`로 트레잇 경계를 정하고 입력 파라메터와 리턴 값의 타입을 모두 `T`로 했다면, 이는 입력과 리턴값이 같은 타입임을 강제합니다. 이렇게 했다면 위의 예제는 동작하지 않았을 것입니다. 왜냐하면, 입력 값의 타입이 `format!`이 리턴하는 타입과 같지 않을 가능성이 높기 때문입니다. 만약 `: Display` 문법을 사용하고 싶다면 독립적인 제네릭 매개변수가 두 개가 필요합니다.\n"
" \n"
"</details>"
#: src/generics/closures.md:1
msgid "# Closures"
@ -9546,13 +9379,9 @@ msgid ""
" `unwrap()` or `expect()` can be called, and this is a signal of the developer intent too. \n"
" * `Result` documentation is a recommended read. Not during the course, but it is worth mentioning. \n"
" It contains a lot of convenience methods and functions that help functional-style programming. \n"
" \n"
"</details>"
msgstr ""
" * `Option`와 마찬가지로, 성공한 경우의 값은 `Result` 내부에 있습니다. 그래서, 개발자는 명시적으로 이를 추출하여야 합니다. 이렇게 함으로써 값을 읽기 전에 오류 발생 여부를 반드시 체크하도록 유도하고 있습니다. 만일 오류가 절대 발생하지 않는 경우라면 `unwrap()`이나 `expect()`를 사용할 수 있으며, 이는 개발자의 의도(_역주_: 오류가 발생할 수 없음)을 명시적으로 나타내는 방법이기도 합니다.\n"
" * 수업중엔 아니지만 `Result`의 API 레퍼런스를 읽는 것을 권장합니다. 함수형 프로그래밍 스타일에 도움이 되는 편리한 메서드와 함수를 많이 배울 수 있습니다.\n"
" \n"
"</details>"
#: src/error-handling/try-operator.md:1
msgid "# Propagating Errors with `?`"
@ -10237,29 +10066,20 @@ msgstr "# 원시 포인터 역참조(따라가기)"
msgid "Creating pointers is safe, but dereferencing them requires `unsafe`:"
msgstr "포인터를 만드는 것은 안전합니다. 하지만 역참조(따라가기)할 경우 `unsafe`가 필요합니다:"
#: src/unsafe/raw-pointers.md:5
msgid ""
"```rust,editable\n"
"fn main() {\n"
" let mut num = 5;"
msgstr ""
"```rust,editable\n"
"fn main() {\n"
" let mut num = 5;"
#: src/unsafe/raw-pointers.md:9
msgid ""
" let mut num = 5;\n"
"\n"
" let r1 = &mut num as *mut i32;\n"
" let r2 = &num as *const i32;"
msgstr ""
" let r1 = &mut num as *mut i32;\n"
" let r2 = &num as *const i32;"
#: src/unsafe/raw-pointers.md:12
msgid ""
" // Safe because r1 and r2 were obtained from references and so are guaranteed to be non-null and\n"
" // properly aligned, the objects underlying the references from which they were obtained are\n"
" // live throughout the whole unsafe block, and they are not accessed either through the\n"
" let r2 = &num as *const i32;\n"
"\n"
" // Safe because r1 and r2 were obtained from references and so are "
"guaranteed to be non-null and\n"
" // properly aligned, the objects underlying the references from which "
"they were obtained are\n"
" // live throughout the whole unsafe block, and they are not accessed "
"either through the\n"
" // references or concurrently through any other pointers.\n"
" unsafe {\n"
" println!(\"r1 is: {}\", *r1);\n"
@ -10269,10 +10089,16 @@ msgid ""
"}\n"
"```"
msgstr ""
" // 아래 코드는 안전합니다. r1과 r2는 참조로 부터 만들어 졌기 때문에 null이 아니며\n"
" // align이 맞다는 것이 보장됩니다. 참조가 가리키는 객체들은 unsafe 블럭이 수행되는\n"
" // 동안 메모리에 살아있습니다. 그리고 이 객체들은 r1과 r2가 아닌 다른 어떤 참조나\n"
" // 포인터로도 접근이 안되고 있습니다.\n"
"```rust,editable\n"
"fn main() {\n"
" let mut num = 5;\n"
"\n"
" let r1 = &mut num as *mut i32;\n"
" let r2 = &num as *const i32;\n"
"\n"
" // 아래 코드는 안전합니다. r1과 r2는 참조로 부터 만들어 졌기 때문에 null이 아니며 align이 맞다는 것이 보장됩니다.\n"
" // 참조가 가리키는 객체들은 unsafe 블럭이 수행되는 동안 메모리에 살아있습니다. 그리고 이 객체들은 r1과 r2가 아닌 다른\n"
" // 어떤 참조나 포인터로도 접근이 안되고 있습니다.\n"
" unsafe {\n"
" println!(\"r1 is: {}\", *r1);\n"
" *r1 = 10;\n"
@ -11039,19 +10865,11 @@ msgstr ""
#: src/concurrency/scoped-threads.md:35
msgid ""
"<details>\n"
" \n"
"* The reason for that is that when the `thread::scope` function completes, all the threads are guaranteed to be joined, so they can return borrowed data.\n"
"* Normal Rust borrowing rules apply: you can either borrow mutably by one thread, or immutably by any number of threads.\n"
" \n"
"</details>"
msgstr ""
"<details>\n"
" \n"
"* `thread::scope` 함수가 완료되면 그 안에서 생성된 모든 스레드들이 종료했음이 보장되기 때문에, 그 때 빌렸던 데이터들을 다시 반환할 수 있기 때문입니다.\n"
"* 일반적인 러스트의 빌림 규칙이 적용됩니다: 한 스레드에 의한 가변 빌림 또는 여러 스레드에 대한 불변 빌림중 하나만 가능합니다.\n"
" \n"
"</details>"
#: src/concurrency/channels.md:1
msgid "# Channels"
@ -11312,8 +11130,6 @@ msgstr ""
#: src/concurrency/shared_state/mutex.md:29
msgid ""
"<details>\n"
" \n"
"* `Mutex` in Rust looks like a collection with just one element - the protected data.\n"
" * It is not possible to forget to acquire the mutex before accessing the protected data.\n"
"* You can get an `&mut T` from an `&Mutex<T>` by taking the lock. The `MutexGuard` ensures that the\n"
@ -11326,8 +11142,6 @@ msgid ""
" fails with a [`PoisonError`]. You can call `into_inner()` on the error to recover the data\n"
" regardless."
msgstr ""
"<details>\n"
" \n"
"* 러스트의 `Mutex`는 오직 하나의 데이터만 담을 수 있는 컬렉션처럼 볼 수도 있습니다. 다른 컬렉션과 다른 점은, 그 데이터가 동시성 문제로부터 자유롭다는 점입니다.\n"
" * `Mutex`는 뮤텍스를 획득하지 않으면 보호된 데이터에 접근하는 것이 불가능 하도록 디자인 되어 있습니다.\n"
"* `&Mutex<T>`에 대해 lock을 획득하면 `&mut T`를 얻을 수 있습니다. `MutexGuard`는 `&mut T`가 획득한 lock보다 오래 살아남지 않음을 보장합니다.\n"
@ -11375,13 +11189,14 @@ msgstr ""
#: src/concurrency/shared_state/example.md:23
msgid ""
"Possible solution:\n"
" \n"
msgstr ""
"가능한 해결방법입니다.:\n"
msgid ""
"```rust,editable\n"
"use std::sync::{Arc, Mutex};\n"
"use std::thread;"
msgstr ""
"가능한 해결방법입니다.:\n"
" \n"
"```rust,editable\n"
"use std::sync::{Arc, Mutex};\n"
"use std::thread;"
@ -11413,26 +11228,6 @@ msgstr ""
msgid " handle.join().unwrap();"
msgstr ""
#: src/concurrency/shared_state/example.md:45
msgid ""
" {\n"
" let v = v.lock().unwrap();\n"
" println!(\"v: {v:?}\");\n"
" }\n"
"}\n"
"```\n"
" \n"
"Notable parts:"
msgstr ""
" {\n"
" let v = v.lock().unwrap();\n"
" println!(\"v: {v:?}\");\n"
" }\n"
"}\n"
"```\n"
" \n"
"참고 사항:"
#: src/concurrency/shared_state/example.md:54
msgid ""
"* `v` is wrapped in both `Arc` and `Mutex`, because their concerns are orthogonal.\n"
@ -11486,13 +11281,10 @@ msgstr ""
msgid ""
"* One can think of these traits as markers that the type has certain thread-safety properties.\n"
"* They can be used in the generic constraints as normal traits.\n"
" \n"
"</details>"
msgstr ""
"* `Sync`와 `Send`는 어떤 타입이 특정한 스레드-안전 속성을 가짐을 나타내는 마커로 생각할 수 있습니다.\n"
"* 이 두 트레잇은 제네릭에서 제약 조건을 나타내는 트레잇로 사용될 수도 있습니다.\n"
"* 이 두 트레이트는 제너릭에서 제약 조건을 나타내는 트레이트로 사용될 수도 있습니다.\n"
"\n"
"</details>"
#: src/concurrency/send-sync/send.md:1
msgid "# `Send`"
@ -13458,19 +13250,8 @@ msgstr ""
#: src/exercises/day-1/solutions-morning.md:73
msgid ""
" let transposed = transpose(matrix);\n"
" println!(\"transposed:\");\n"
" pretty_print(&transposed);\n"
"}\n"
"```\n"
"### Bonus question"
msgstr ""
" let transposed = transpose(matrix);\n"
" println!(\"transposed:\");\n"
" pretty_print(&transposed);\n"
"}\n"
"```\n"
"\n"
"### 보너스 문제"
#: src/exercises/day-1/solutions-morning.md:80

View File

@ -3300,13 +3300,14 @@ msgstr ""
#: src/basic-syntax/type-inference.md:26
msgid ""
"This slide demonstrates how the Rust compiler infers types based on constraints given by variable declarations and usages.\n"
" \n"
msgstr ""
"Este slide demonstra como o compilador Rust infere tipos com base em restrições dadas por declarações e usos de variáveis.\n"
msgid ""
"It is very important to emphasize that variables declared like this are not of some sort of dynamic \"any type\" that can\n"
"hold any data. The machine code generated by such declaration is identical to the explicit declaration of a type.\n"
"The compiler does the job for us and helps us to write a more concise code."
msgstr ""
"Este slide demonstra como o compilador Rust infere tipos com base em restrições dadas por declarações e usos de variáveis.\n"
" \n"
"É muito importante enfatizar que variáveis declaradas assim não são de um tipo dinâmico \"qualquer tipo\" que possa\n"
"armazenar quaisquer dados. O código de máquina gerado por tal declaração é idêntico à declaração explícita de um tipo.\n"
"O compilador faz o trabalho para nós e nos ajuda a escrever um código mais conciso."
@ -4398,61 +4399,24 @@ msgstr ""
#: src/ownership/borrowing.md:27
msgid ""
"Notes on stack returns:\n"
msgstr ""
"Notas sobre retornos de pilha:\n"
msgid ""
"* Demonstrate that the return from `add` is cheap because the compiler can eliminate the copy operation. Change the above "
"code to print stack addresses and run it on the [Playground]. In the \"DEBUG\" optimization level, the addresses should "
"change, while the stay the same when changing to the \"RELEASE\" setting:"
msgstr ""
"Notas sobre retornos de pilha:\n"
"* Demonstre que o retorno de `add` é barato porque o compilador pode eliminar a operação de cópia. Altere o código acima "
"para imprimir endereços de pilha e execute-o no [Playground]. No nível de otimização \"DEBUG\", os endereços devem mudar, "
"enquanto os permanecem os mesmos ao mudar para a configuração \"RELEASE\":"
#: src/ownership/borrowing.md:30
msgid ""
" ```rust,editable\n"
" #[derive(Debug)]\n"
" struct Point(i32, i32);"
msgstr ""
" ```rust, editable\n"
" #[derive(Debug)]\n"
" struct Point(i32, i32);"
#: src/ownership/borrowing.md:34
msgid ""
" fn add(p1: &Point, p2: &Point) -> Point {\n"
" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n"
" println!(\"&p.0: {:p}\", &p.0);\n"
" p\n"
" }"
msgstr ""
" fn add(p1: &Point, p2: &Point) -> Point {\n"
" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n"
" println!(\"&p.0: {:p}\", &p.0);\n"
" p\n"
" }"
#: src/ownership/borrowing.md:40
msgid ""
" fn main() {\n"
" let p1 = Point(3, 4);\n"
" let p2 = Point(10, 20);\n"
" let p3 = add(&p1, &p2);\n"
" println!(\"&p3.0: {:p}\", &p3.0);\n"
" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n"
" }\n"
" ```\n"
"* The Rust compiler can do return value optimization (RVO).\n"
"* In C++, copy elision has to be defined in the language specification because constructors can have side effects. In Rust, "
"this is not an issue at all. If RVO did not happen, Rust will always performs a simple and efficient `memcpy` copy."
msgstr ""
" fn main() {\n"
" let p1 = Point(3, 4);\n"
" let p2 = Point(10, 20);\n"
" let p3 = add(&p1, &p2);\n"
" println!(\"&p3.0: {:p}\", &p3.0);\n"
" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n"
" }\n"
" ```\n"
"* O compilador Rust pode fazer otimização de valor de retorno (RVO).\n"
"* Em C++, a elisão de cópia deve ser definida na especificação da linguagem porque os construtores podem ter efeitos "
"colaterais. Em Rust, isso não é um problema. Se o RVO não aconteceu, o Rust sempre executará uma cópia `memcpy` simples e "
@ -4993,12 +4957,8 @@ msgstr ""
#: src/exercises/day-1/book-library.md:99
msgid ""
"<details>\n"
" \n"
"[Solution](solutions-afternoon.md#designing-a-library)"
msgstr ""
"<details>\n"
" \n"
"[Solution](solutions-afternoon.md#designing-a-library)"
#: src/exercises/day-1/iterators-and-ownership.md:1
@ -5349,10 +5309,8 @@ msgstr ""
#: src/structs.md:29
msgid ""
"<details>\n"
"Key Points: "
msgstr ""
"<details>\n"
"Points chave:"
#: src/structs.md:32
@ -5460,18 +5418,17 @@ msgstr "```"
#: src/structs/tuple-structs.md:37
msgid ""
"Newtypes are a great way to encode additional information about the value in a primitive type, for example:\n"
msgstr ""
"Newtypes são uma ótima maneira de codificar informações adicionais sobre o valor em um tipo primitivo, por exemplo:\n"
msgid ""
" * The number is measured in some units: `Newtons` in the example above.\n"
" * The value passed some validation when it was created, so you no longer have to validate it again at every use: "
"'PhoneNumber(String)` or `OddNumber(u32)`.\n"
" \n"
"</details>"
msgstr ""
"Newtypes são uma ótima maneira de codificar informações adicionais sobre o valor em um tipo primitivo, por exemplo:\n"
" * O número é medido em algumas unages: `Newtons` no exemplo acima.\n"
" * O valor passou por alguma validação quando foi criado, então você não precisa mais validá-lo novamente a cada uso: "
"'PhoneNumber(String)` ou `OddNumber(u32)`.\n"
" \n"
"</details>"
#: src/structs/field-shorthand.md:1
msgid "# Field Shorthand Syntax"
@ -5627,12 +5584,8 @@ msgstr ""
#: src/enums.md:31
msgid ""
"<details>\n"
" \n"
"Key Points:"
msgstr ""
"<details>\n"
" \n"
"Points chave:"
#: src/enums.md:35
@ -5814,9 +5767,6 @@ msgstr "* Consulte a [Referência Rust](https://doc.rust-lang.org/reference/type
#: src/enums/sizes.md:39
msgid ""
"<details>\n"
" \n"
"Key Points: \n"
" * Internally Rust is using a field (discriminant) to keep track of the enum variant.\n"
" * `Bar` enum demonstrates that there is a way to control the discriminant value and type. If `repr` is removed, the "
"discriminant type takes 2 bytes, becuase 10001 fits 2 bytes.\n"
@ -5827,9 +5777,6 @@ msgid ""
"`size_of::<Option<T>>()`.\n"
" * Zero-sized types allow for efficient implementation of `HashSet` using `HashMap` with `()` as the value."
msgstr ""
"<details>\n"
" \n"
"Points chave:\n"
" * Internamente Rust está usando um campo (discriminante) para acompanhar a variante enum.\n"
" * A Enum `Bar` demonstra que existe uma maneira de controlar o valor e o tipo discriminante. Se `repr` for removido, o "
"tipo discriminante ocupa 2 bytes, porque 10001 cabe 2 bytes.\n"
@ -6011,7 +5958,6 @@ msgstr ""
#: src/methods.md:30
msgid ""
"Key Points:\n"
"* It can be helpful to introduce methods by comparing them to functions.\n"
" * Methods are called on an instance of a type (such as a struct or enum), the first parameter represents the instance as "
"`self`.\n"
@ -6027,7 +5973,6 @@ msgid ""
" \n"
"</details>"
msgstr ""
"Points chave:\n"
"* Pode ser útil introduzir métodos comparando-os com funções.\n"
" * Métodos são chamados em uma instância de um tipo (como struct ou enum), o primeiro parâmetro representa a instância "
"como `self`.\n"
@ -6097,16 +6042,12 @@ msgstr ""
#: src/methods/receiver.md:23
msgid ""
"<details>\n"
" \n"
"Consider emphasizing on \"shared and immutable\" and \"unique and mutable\". These constraints always come\n"
"together in Rust due to borrow checker rules, and `self` is no exception. It won't be possible to\n"
"reference a struct from multiple locations and call a mutating (`&mut self`) method on it.\n"
" \n"
"</details>"
msgstr ""
"<details>\n"
" \n"
"Considere enfatizar \"compartilhado e imutável\" e \"único e mutável\". Essas restrições sempre vêm\n"
"juntos no Rust devido às regras do verificador emprestado, e `self` não é exceção. Não será possível\n"
"referenciar um struct de vários locais e chamar um método mutante (`&mut self`) nele.\n"
@ -6213,9 +6154,6 @@ msgstr ""
#: src/methods/example.md:44
msgid ""
"<details>\n"
" \n"
"Key Points:\n"
"* All four methods here use a different method receiver.\n"
" * You can point out how that changes what the function can do with the variable values and if/how it can be used again in "
"`main`.\n"
@ -6226,9 +6164,6 @@ msgid ""
"* You might point out that `print_laps` is using a vector that is iterated over. We describe vectors in more detail in the "
"afternoon. "
msgstr ""
"<details>\n"
" \n"
"Points chave:\n"
"* Todos os quatro métodos aqui usam um receptor de método diferente.\n"
" * Você pode apontar como isso muda o que a função pode fazer com os valores das variáveis e se/como ela pode ser usada "
"novamente em `main`.\n"
@ -6290,9 +6225,6 @@ msgstr "O padrão `_` é um padrão curinga que corresponde a qualquer valor."
#: src/pattern-matching.md:23
msgid ""
"<details>\n"
" \n"
"Key Points:\n"
"* You might point out how some specific characters are being used when in a pattern\n"
" * `|` as an `or`\n"
" * `..` can expand as much as it needs to be\n"
@ -6305,9 +6237,6 @@ msgid ""
" \n"
"</details>"
msgstr ""
"<details>\n"
" \n"
"Points chave:\n"
"* Você pode apontar como alguns caracteres específicos estão sendo usados quando em um padrão\n"
" * `|` como um `ou`\n"
" * `..` pode expandir o quanto for necessário\n"
@ -6392,12 +6321,10 @@ msgstr ""
#: src/pattern-matching/destructuring-enums.md:35
msgid ""
"Key points:\n"
"* The `if`/`else` expression is returning an enum that is later unpacked with a `match`.\n"
"* You can try adding a third variant to the enum definition and displaying the errors when running the code. Point out the "
"places where your code is now inexhaustive and how the compiler tries to give you hints."
msgstr ""
"Points chave:\n"
"* A expressão `if`/`else` está retornando um enum que é posteriormente descompactado com um `match`.\n"
"* Você pode tentar adicionar uma terceira variante à definição de Enum e exibir os erros ao executar o código. Aponte os "
"lugares onde seu código agora é inexaustivo e como o compilador tenta lhe dar dicas."
@ -6436,7 +6363,6 @@ msgid ""
" }\n"
"}\n"
"```\n"
"<details>"
msgstr ""
"#[rustfmt::pular]\n"
"fn main() {\n"
@ -6447,7 +6373,7 @@ msgstr ""
" Foo { y, .. } => println!(\"y = {y}, outros campos foram ignorados\"),\n"
" }\n"
"}\n"
"```"
"```\n"
#: src/pattern-matching/destructuring-structs.md:23
msgid ""
@ -6504,10 +6430,6 @@ msgid ""
" inspect(&[0, -2, 3]);\n"
" inspect(&[0, -2, 3, 4]);\n"
"}"
msgstr ""
#: src/pattern-matching/destructuring-arrays.md:28
msgid ""
"#[rustfmt::skip]\n"
"fn inspect(slice: &[i32]) {\n"
" println!(\"Tell me about {slice:?}\");\n"
@ -6518,8 +6440,11 @@ msgid ""
" }\n"
"}\n"
"```\n"
msgstr ""
#: src/pattern-matching/destructuring-arrays.md:28
msgid ""
"* Show matching against the tail with patterns `[.., b]` and `[a@..,b]`\n"
"</details>"
msgstr ""
#: src/pattern-matching/match-guards.md:1
@ -6566,7 +6491,6 @@ msgstr ""
#: src/pattern-matching/match-guards.md:22
msgid ""
"Key Points:\n"
"* Match guards as a separate syntax feature are important and necessary when we wish to concisely express more complex "
"ideas than patterns alone would allow.\n"
"* They are not the same as separate `if` expression inside of the match arm. An `if` expression inside of the branch block "
@ -6577,7 +6501,6 @@ msgid ""
"* The condition defined in the guard applies to every expression in a pattern with an `|`.\n"
"</details>"
msgstr ""
"Points chave:\n"
"* Match guards como um recurso de sintaxe separado são importantes e necessários.\n"
"* Eles não são iguais à expressão 'if' separada dentro do braço de correspondência. Uma expressão `if` dentro do bloco de "
"ramificação (depois de `=>`) acontece depois que o braço de correspondência é selecionado. A falha na condição `if` dentro "
@ -7042,13 +6965,13 @@ msgstr ""
#: src/exercises/day-2/points-polygons.md:120
msgid ""
"Other interesting parts of the exercise:\n"
" \n"
"* Derive a `Copy` trait for some structs, as in tests the methods sometimes don't borrow their arguments.\n"
msgstr ""
"Outras partes interessantes do exercício:\n"
msgid "* Derive a `Copy` trait for some structs, as in tests the methods sometimes don't borrow their arguments.\n"
"* Discover that `Add` trait must be implemented for two objects to be addable via \"+\". Note that we do not discuss "
"generics until Day 3."
msgstr ""
"Outras partes interessantes do exercício:\n"
" \n"
"* Derive um trait `Copy` para algumas Structs, já que em testes os métodos às vezes não emprestam seus argumentos.\n"
"* Descubra que o trait `Add` deve ser implementado para que dois objetos sejam adicionados via \"+\"."
@ -7151,14 +7074,12 @@ msgstr "No entanto, se a última expressão terminar com `;`, o valor e o tipo r
#: src/control-flow/blocks.md:42
msgid ""
"Key Points:\n"
"* The point of this slide is to show that blocks have a type and value in Rust. \n"
"* You can show how the value of the block changes by changing the last line in the block. For instance, adding/removing a "
"semicolon or using a `return`.\n"
" \n"
"</details>"
msgstr ""
"Points chave:\n"
"* O objetivo deste slide é mostrar que os blocos têm um tipo e valor em Rust.\n"
"* Você pode mostrar como o valor do bloco muda alterando a última linha do bloco. Por exemplo, adicionar/remover um Point e "
"vírgula ou usar um `return`.\n"
@ -7444,16 +7365,12 @@ msgstr "Você pode usar `break` e `continue` aqui como de costume."
#: src/control-flow/for-expressions.md:22
msgid ""
"<details>\n"
" \n"
"* Index iteration is not a special syntax in Rust for just that case.\n"
"* `(0..10)` is a range that implements an `Iterator` trait. \n"
"* `step_by` is a method that returns another `Iterator` that skips every other element. \n"
"* Modify the elements in the vector and explain the compiler errors. Change vector `v` to be mutable and the for loop to "
"`for x in v.iter_mut()`."
msgstr ""
"<details>\n"
" \n"
"* A iteração de índice não é uma sintaxe especial no Rust apenas para esse caso.\n"
"* `(0..10)` é um intervalo que implementa uma característica `Iterator`.\n"
"* `step_by` é um método que retorna outro `Iterator` que pula todos os outros elementos.\n"
@ -7494,8 +7411,6 @@ msgstr ""
#: src/control-flow/loop-expressions.md:23
msgid ""
"<details>\n"
" \n"
"* Break the `loop` with a value (e.g. `break 8`) and print it out."
msgstr ""
@ -7549,8 +7464,6 @@ msgstr ""
#: src/control-flow/match-expressions.md:25
msgid ""
"<details>\n"
" \n"
"* Save the match expression to a variable and print it out.\n"
"* Remove `.as_deref()` and explain the error.\n"
" * `std::env::Agrs().next` returns an `Option<&String>`, but we cannot match against `String`.\n"
@ -7668,16 +7581,12 @@ msgstr "* [`Rc`](std/rc.md): um ponteiro de contagem de referência compartilhad
#: src/std.md:23
msgid ""
"<details>\n"
" \n"
" * In fact, Rust contains several layers of the Standard Library: `core`, `alloc` and `std`. \n"
" * `core` includes the most basic types and functions that don't depend on `libc`, allocator or\n"
" even the presence of an operating system. \n"
" * `alloc` includes types which require a global heap allocator, such as `Vec`, `Box` and `Arc`.\n"
" * Embedded Rust applications often only use `core`, and sometimes `alloc`."
msgstr ""
"<details>\n"
" \n"
" * Na verdade, Rust contém várias camadas da Biblioteca Padrão: `core`, `alloc` e `std`.\n"
" * `core` inclui os tipos e funções mais básicos que não dependem de `libc`, alocador ou\n"
" até mesmo a presença de um sistema operacional.\n"
@ -8143,16 +8052,12 @@ msgstr ""
#: src/std/box-recursive.md:33
msgid ""
"<details>\n"
" \n"
"* If the `Box` was not used here and we attempted to embed a `List` directly into the `List`,\n"
"the compiler would not compute a fixed size of the struct in memory, it would look infinite.\n"
" \n"
"* `Box` solves this problem as it has the same size as a regular pointer and just points at the next\n"
"element of the `List` in the heap. "
msgstr ""
"<details>\n"
" \n"
"Se a `Caixa` não foi usada aqui e tentamos incorporar uma `Lista` diretamente na `Lista`,\n"
"o compilador não calcularia um tamanho fixo da estrutura na memória, pareceria infinito.\n"
" \n"
@ -8985,20 +8890,8 @@ msgstr ""
#: src/traits.md:46
msgid ""
"Compare these outputs in the above example:\n"
"```rust,ignore\n"
" println!(\"{} {}\", std::mem::size_of::<Dog>(), std::mem::size_of::<Cat>());\n"
" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n"
" println!(\"{}\", std::mem::size_of::<&dyn Greet>());\n"
" println!(\"{}\", std::mem::size_of::<Box<dyn Greet>>());\n"
"```"
msgstr ""
"Compare essas saídas no exemplo acima:\n"
"```rust, ignore\n"
" println!(\"{} {}\", std::mem::size_of::<Dog>(), std::mem::size_of::<Cat>());\n"
" println!(\"{} {}\", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());\n"
" println!(\"{}\", std::mem::size_of::<&dyn Greet>());\n"
" println!(\"{}\", std::mem::size_of::<Box<dyn Greet>>());\n"
"```"
#: src/traits/deriving-traits.md:1
msgid "# Deriving Traits"
@ -9199,10 +9092,6 @@ msgstr ""
" \n"
"</details>"
#: src/traits/iterator.md:41
msgid "[1]: https://doc.rust-lang.org/std/iter/trait.Iterator.html"
msgstr "[1]: https://doc.rust-lang.org/std/marker/trait.Send.html"
#: src/traits/from-iterator.md:1
msgid "# FromIterator"
msgstr "# FromIterator"
@ -9241,14 +9130,6 @@ msgstr ""
"Também existem implementações que permitem fazer coisas legais como converter um\n"
"`Iterator<Item = Result<V, E>>` em um `Result<Vec<V>, E>`."
#: src/traits/from-iterator.md:28
msgid ""
"[1]: https://doc.rust-lang.org/std/iter/trait.FromIterator.html\n"
"[2]: https://doc.rust-lang.org/std/iter/trait.Iterator.html"
msgstr ""
"[1]: https://doc.rust-lang.org/std/iter/trait.FromIterator.html\n"
"[2]: https://doc.rust-lang.org/std/iter/trait.Iterator.html"
#: src/traits/from-into.md:1
msgid "# `From` and `Into`"
msgstr "# `De` e `Into`"
@ -9290,8 +9171,6 @@ msgstr ""
#: src/traits/from-into.md:27
msgid ""
"<details>\n"
" \n"
"* That's why it is common to only implement `From`, as your type will get `Into` implementation too.\n"
"* When declaring a function argument input type like \"anything that can be converted into a `String`\", the rule is "
"opposite, you should use `Into`.\n"
@ -9299,8 +9178,6 @@ msgid ""
" \n"
"</details>"
msgstr ""
"<details>\n"
" \n"
"* É por isso que é comum implementar apenas `From`, já que seu tipo também receberá implementação `Into`.\n"
"* Ao declarar um tipo de entrada de argumento de função como \"qualquer coisa que possa ser convertida em `String`\", a "
"regra é oposta, você deve usar `Into`.\n"
@ -9308,14 +9185,6 @@ msgstr ""
" \n"
"</details>"
#: src/traits/from-into.md:35
msgid ""
"[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n"
"[2]: https://doc.rust-lang.org/std/convert/trait.Into.html"
msgstr ""
"[1]: https://doc.rust-lang.org/std/convert/trait.From.html\n"
"[2]: https://doc.rust-lang.org/std/convert/trait.Into.html"
#: src/traits/read-write.md:1
msgid "# `Read` and `Write`"
msgstr "# `Read` e `Write`"
@ -12554,16 +12423,12 @@ msgstr "[1]: https://doc.rust-lang.org/std/thread/fn.scope.html"
#: src/concurrency/scoped-threads.md:35
msgid ""
"<details>\n"
" \n"
"* The reason for that is that when the `thread::scope` function completes, all the threads are guaranteed to be joined, so "
"they can return borrowed data.\n"
"* Normal Rust borrowing rules apply: you can either borrow mutably by one thread, or immutably by any number of threads.\n"
" \n"
"</details>"
msgstr ""
"<details>\n"
" \n"
"* A razão para isso é que, quando a função `thread::scope` for concluída, todas as threads serão unidas, para que possam "
"retornar dados emprestados.\n"
"* Aplicam-se as regras normais de empréstimo do Rust: você pode emprestar mutável por um encadeamento ou imutavelmente por "
@ -12889,8 +12754,6 @@ msgstr ""
#: src/concurrency/shared_state/mutex.md:30
msgid ""
"<details>\n"
" \n"
"* `Mutex` in Rust looks like a collection with just one element - the protected data.\n"
" * It is not possible to forget to acquire the mutex before accessing the protected data.\n"
"* You can get an `&mut T` from an `&Mutex<T>` by taking the lock. The `MutexGuard` ensures that the\n"
@ -12903,8 +12766,6 @@ msgid ""
" fails with a [`PoisonError`]. You can call `into_inner()` on the error to recover the data\n"
" regardless."
msgstr ""
"<details>\n"
" \n"
"* `Mutex` em Rust parece uma coleção com apenas um elemento - os dados protegidos.\n"
" * Não é possível esquecer de adquirir o mutex antes de acessar os dados protegidos.\n"
"* Você pode obter um `&mut T` de um `&Mutex<T>` pegando o bloqueio. O `MutexGuard` garante que o\n"
@ -12972,22 +12833,16 @@ msgstr ""
#: src/concurrency/shared_state/example.md:23
msgid ""
"Possible solution:\n"
" \n"
"```rust,editable\n"
"use std::sync::{Arc, Mutex};\n"
"use std::thread;"
msgstr ""
"Solução possível:\n"
" \n"
"```rust, editable\n"
"use std::sync::{Arc, Mutex};\n"
"use std::thread;"
#: src/concurrency/shared_state/example.md:29
msgid ""
"```rust,editable\n"
"fn main() {\n"
" let v = Arc::new(Mutex::new(vec![10, 20, 30]));"
msgstr ""
"```rust,editable\n"
"fn main() {\n"
" let v = Arc::new(Mutex::new(vec![10, 20, 30]));"
@ -13021,25 +12876,8 @@ msgstr ""
msgid " handle.join().unwrap();"
msgstr " handle.join().unwrap();"
#: src/concurrency/shared_state/example.md:45
msgid ""
" {\n"
" let v = v.lock().unwrap();\n"
" println!(\"v: {v:?}\");\n"
" }\n"
"}\n"
"```\n"
" \n"
"Notable parts:"
msgstr ""
" {\n"
" let v = v.lock().unwrap();\n"
" println!(\"v: {v:?}\");\n"
" }\n"
"}\n"
"```\n"
" \n"
"Partes notáveis:"
msgid "Notable parts:"
msgstr "Partes notáveis:"
#: src/concurrency/shared_state/example.md:54
msgid ""
@ -15805,14 +15643,15 @@ msgid ""
" pretty_print(&transposed);\n"
"}\n"
"```\n"
"### Bonus question"
msgstr ""
" let transposed = transpose(array);\n"
" println!(\"transposto:\");\n"
" pretty_print(&transposed);\n"
"}\n"
"```\n"
"### Pergunta bônus"
msgid "### Bonus question"
msgstr "### Pergunta bônus"
#: src/exercises/day-1/solutions-morning.md:80
msgid ""