Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

번역

rustc의 현재 진단 번역 인프라는( 2024년 10월 기준) 안타깝게도 컴파일러 기여자에게 다소 불편을 주고 있으며, 현재 인프라는 컴파일러 기여자와 번역 팀 양쪽의 요구를 더 잘 반영하는 재설계를 대체로 기다리고 있는 상태입니다. 현재 활발히 진행 중인 재설계 제안은 없다는 점에 유의하십시오( 2024년 10월 기준)!

진행 상황은 추적 이슈 https://github.com/rust-lang/rust/issues/132181를 참고하십시오.

번역 인프라는 아직 제안되지 않은 재설계와 그에 따른 재작업을 기다리고 있으므로, 현재 번역 인프라의 사용을 의무화하지 않습니다. 인프라를 사용하고 싶거나 인프라를 쓰는 편이 코드를 더 깔끔하게 만든다면 사용하되, 그렇지 않고 더 많은 유연성이 필요하다면 번역 인프라를 우회하십시오.

rustc의 진단 인프라는 Fluent를 사용하여 번역 가능한 진단을 지원합니다.

번역 가능한 진단 작성하기

번역 가능한 진단을 작성하는 방법에는 두 가지가 있습니다:

  1. 단순한 진단의 경우, 진단(또는 하위 진단) derive를 사용합니다. (“단순한” 진단이란 하위 진단을 내보낼지 결정하는 데 많은 로직이 필요하지 않아서 진단 구조체로 표현할 수 있는 진단을 말합니다.) 진단 및 하위 진단 구조체 문서를 참고하십시오.
  2. Diag API와 함께 타입이 지정된 식별자를 사용합니다(Diagnostic 또는 Subdiagnostic 구현 안에서).

번역 가능한 진단을 추가하거나 변경할 때 번역은 신경 쓰지 않아도 됩니다. 원본 영어 메시지만 수정하면 됩니다.

Fluent

Fluent는 “비대칭 현지화(asymmetric localization)“라는 개념을 바탕으로 만들어졌으며, 이는 번역의 표현력을 원본 언어(rustc의 경우 영어)의 문법에서 분리하는 것을 목표로 합니다. 번역 기능이 도입되기 전에는 rustc의 진단이 사용자에게 표시되는 메시지를 빌드하기 위해 보간에 크게 의존했습니다. 보간된 문자열은 번역하기 어렵습니다. 자연스러운 번역을 쓰려면 영어 문자열보다 보간이 더 많이, 더 적게, 또는 다르게 필요할 수 있는데, 이 모든 경우를 지원하려면 컴파일러의 소스 코드를 변경해야 하기 때문입니다.

진단 메시지는 Fluent 리소스에 정의됩니다. 특정 로캘(예: en-US)에 대한 Fluent 리소스를 모두 합친 집합을 Fluent 번들이라고 합니다.

typeck_address_of_temporary_taken = cannot take address of a temporary

위 예시에서 typeck_address_of_temporary_taken은 Fluent 메시지의 식별자이며, 영어로 된 진단 메시지에 대응합니다. 다른 언어의 메시지에 대응하는 Fluent 리소스를 따로 작성할 수 있습니다. 따라서 각 진단에는 적어도 하나의 Fluent 메시지가 있습니다.

typeck_address_of_temporary_taken = cannot take address of a temporary
    .label = temporary value

관례적으로 하위 진단의 진단 메시지는 Fluent 메시지의 “속성(attribute)“으로 지정합니다(속성은 관련된 추가 메시지로, .<attribute-name> 구문으로 표기합니다). 위 예시에서 label은 typeck_address_of_temporary_taken의 속성이며, 이 진단에 추가되는 레이블의 메시지에 대응합니다.

진단 메시지는 타입이나 변수의 이름처럼 추가적인 맥락을 사용자에게 보여 줄 메시지에 보간하는 경우가 많습니다. Fluent 메시지에 들어갈 추가 컨텍스트는 진단에 “인자“로 제공됩니다.

typeck_struct_expr_non_exhaustive =
    cannot create non-exhaustive {$what} using struct expression

위 예시에서 Fluent 메시지는 what이라는 이름의 인자를 참조하며, 이 인자는 존재한다고 가정됩니다(진단에 인자를 제공하는 방법은 뒤에서 자세히 다룹니다).

Fluent의 다른 사용 예시와 구문은 Fluent 문서를 참고하십시오.

메시지 이름 지정 지침

일반적으로 fluent는 메시지 이름 안에서 단어를 구분할 때 -를 사용합니다. 하지만 fluent는 _도 허용합니다. Rust 쪽 식별자도 _를 사용하므로 _가 Rust의 사용 사례에 더 잘 맞습니다. 따라서 rustc 내부에서는 단어 구분에 -를 사용할 수 없으며, 대신 _를 사용하는 것을 권장합니다. 유일한 예외는 -passes_see_issue와 같은 메시지 이름에서 맨 앞에 오는 -입니다.

번역 가능한 메시지 작성 지침

메시지를 여러 언어로 번역할 수 있으려면, 영어 메시지에 필요한 정보뿐만 아니라 어떤 언어에서든 필요한 모든 정보를 진단에 인자로 제공해야 합니다.

컴파일러 팀이 여러 언어로 번역하는 데 필요한 모든 정보를 갖춘 진단을 작성하는 경험을 더 쌓아 감에 따라, 이 페이지에 더 많은 지침이 추가될 것입니다. 현재로서는 Fluent 문서에 메시지를 여러 로캘로 번역하는 훌륭한 예시와, 이를 위해 코드가 제공해야 하는 정보가 잘 나와 있습니다.

컴파일 타임 검증과 타입이 지정된 식별자

rustc의 #[derive(Diagnostic)] 매크로는 Fluent 메시지에 대한 컴파일 타임 검증을 수행합니다. Fluent 리소스에 대한 컴파일 타임 검증은 컴파일러를 빌드하는 동안 Fluent 리소스의 파싱 오류를 모두 보고하므로, 잘못된 Fluent 리소스로 인해 컴파일러에서 패닉이 발생하는 것을 방지합니다. 또한 컴파일 타임 검증은 여러 Fluent 메시지가 같은 식별자를 가지는 경우에도 오류를 보고합니다.

내부 구조

번역을 지원하기 위해 rustc 진단 내부 구조의 여러 부분이 수정되었습니다.

메시지

rustc의 기존 진단 API(예: struct_span_err나 note)는 모두 DiagMessage로 변환할 수 있는 메시지라면 무엇이든 받습니다.

rustc_error_messages::DiagMessage는 번역할 수 없는 레거시 진단 메시지와 번역 가능한 메시지를 모두 표현할 수 있습니다. 번역할 수 없는 메시지는 단순한 String입니다. 번역 가능한 메시지는 Fluent 메시지의 식별자를 담은 &'static str일 뿐입니다(경우에 따라 속성을 담은 &'static str가 추가로 붙기도 합니다).

DiagMessage를 직접 다룰 필요는 전혀 없습니다. Fluent 리소스의 각 진단 메시지마다 DiagMessage 상수가 생성되거나(아래에서 자세히 설명합니다), 진단 derive의 매크로가 생성한 코드에서 DiagMessage가 만들어집니다.

DiagMessage는 문자열로 변환할 수 있는 모든 타입에 대해 Into를 구현하며, 이러한 타입을 번역할 수 없는 진단으로 변환합니다. 덕분에 기존의 모든 진단 호출이 그대로 동작합니다.

인자

메시지 내용에 보간되는 Fluent 메시지의 추가 컨텍스트를 번역 가능한 진단에 제공해야 합니다.

진단에는 이러한 추가 컨텍스트를 진단에 제공하는 데 사용할 수 있는 set_arg 함수가 있습니다.

인자는 이름(예: 앞의 예시에서 “what”)과 값을 모두 가집니다. 인자 값은 DiagArgValue 타입으로 표현되며, 이 타입은 단순히 문자열 또는 숫자입니다. rustc 타입은 문자열이나 숫자로 변환하는 방식으로 IntoDiagArg를 구현할 수 있으며, Ty<'tcx> 같은 일반적인 타입에는 이미 그러한 구현이 있습니다.

set_arg 호출은 진단 derive가 투명하게 처리하지만, 진단 빌더 API를 사용할 때는 직접 추가해야 합니다.