# Translation
<div class="warning">
rustc's current diagnostics translation infrastructure (as of
<!-- date-check --> October 2024
) unfortunately causes some friction for compiler contributors, and the current
infrastructure is mostly pending a redesign that better addresses needs of both
compiler contributors and translation teams. Note that there is no current
active redesign proposals (as of
<!-- date-check --> October 2024
)!
Please see the tracking issue <https://github.com/rust-lang/rust/issues/132181>
for status updates.
We have downgraded the internal lints `untranslatable_diagnostic` and
`diagnostic_outside_of_impl`. Those internal lints previously required new code
to use the current translation infrastructure. However, because the translation
infra is waiting for a yet-to-be-proposed redesign and thus rework, we are not
mandating usage of current translation infra. Use the infra if you *want to* or
otherwise makes the code cleaner, but otherwise sidestep the translation infra
if you need more flexibility.
</div>
rustc's diagnostic infrastructure supports translatable diagnostics using
[Fluent].
## Writing translatable diagnostics
There are two ways of writing translatable diagnostics:
1. For simple diagnostics, using a diagnostic (or subdiagnostic) derive.
("Simple" diagnostics being those that don't require a lot of logic in
deciding to emit subdiagnostics and can therefore be represented as
diagnostic structs). See [the diagnostic and subdiagnostic structs
documentation](./diagnostic-structs.md).
2. Using typed identifiers with `Diag` APIs (in
`Diagnostic` or `Subdiagnostic` or `LintDiagnostic` implementations).
When adding or changing a translatable diagnostic,
you don't need to worry about the translations.
Only updating the original English message is required.
Currently,
each crate which defines translatable diagnostics has its own Fluent resource,
which is a file named `messages.ftl`,
located in the root of the crate
(such as`compiler/rustc_expand/messages.ftl`).
## Fluent
Fluent is built around the idea of "asymmetric localization", which aims to
decouple the expressiveness of translations from the grammar of the source
language (English in rustc's case). Prior to translation, rustc's diagnostics
relied heavily on interpolation to build the messages shown to the users.
Interpolated strings are hard to translate because writing a natural-sounding
translation might require more, less, or just different interpolation than the
English string, all of which would require changes to the compiler's source
code to support.
Diagnostic messages are defined in Fluent resources. A combined set of Fluent
resources for a given locale (e.g. `en-US`) is known as Fluent bundle.
```fluent
typeck_address_of_temporary_taken = cannot take address of a temporary
```
In the above example, `typeck_address_of_temporary_taken` is the identifier for
a Fluent message and corresponds to the diagnostic message in English. Other
Fluent resources can be written which would correspond to a message in another
language. Each diagnostic therefore has at least one Fluent message.
```fluent
typeck_address_of_temporary_taken = cannot take address of a temporary
.label = temporary value
```
By convention, diagnostic messages for subdiagnostics are specified as
"attributes" on Fluent messages (additional related messages, denoted by the
`.<attribute-name>` syntax). In the above example, `label` is an attribute of
`typeck_address_of_temporary_taken` which corresponds to the message for the
label added to this diagnostic.
Diagnostic messages often interpolate additional context into the message shown
to the user, such as the name of a type or of a variable. Additional context to
Fluent messages is provided as an "argument" to the diagnostic.
```fluent
typeck_struct_expr_non_exhaustive =
cannot create non-exhaustive {$what} using struct expression
```
In the above example, the Fluent message refers to an argument named `what`