Description
Important
Please see #132181 for the current status of the compiler's translatable diagnostics infrastructure.
The Rust Diagnostics working group is leading an effort to add support for internationalization of error messages in the compiler, allowing the compiler to produce output in languages other than English. This issue tracks the current status of the effort, which was announced in the "Contribute to the diagnostic translation effort!" post on Inside Rust.
What's the current status?
Diagnostic translation will take a long time to be finished. At a high-level, there are four primary steps:
- Implement initial translation infrastructure
- Make diagnostics translatable through migration to new infrastructure (we are here)
- Set up Pontoon for translators to use
- Establish translation teams for different languages
- Implement infrastructure for distributing language packs in collaboration with infrastructure/release teams (as appropriate)
Implementing the initial translation infrastructure provides the groundwork that enables diagnostic messages to be made translatable at all. That initial infrastructure is largely completed - there might be some gaps that we'll discover and patch up as we continue - but it's almost all there.
Next, all of the diagnostics in rustc need to be modified so that they can be translatable. There's some bad news - that's a lot of work. But there's also some good news - that's a lot of highly parallelizable work that you can help with! It doesn't require any familiarity with the Rust compiler, just an eagerness to get involved.
How to get started?
It's very easy to get started, the process looks like the following:
- Join our Zulip chat and say hello! Everyone is very friendly and eager to help if you have any trouble.
- Set up a development environment for the compiler.
- Identify a module to migrate (see "Identifying diagnostics to migrate" below).
- Migrate diagnostics (see "Migrate diagnostics" below).
- Open a pull request with your changes.
- Repeat and profit!
Identifying diagnostics to migrate
Our goal is to migrate every diagnostic in the compiler to be translatable and to switch from using a "diagnostic builder" to using "diagnostic structs". That's a lot of diagnostics, so we're splitting the work up by module in the compiler so that nobody steps on anyone else's toes.
-
rustc_apfloat
-
rustc_arena
-
rustc_ast
-
rustc_ast_lowering
-
rustc_ast_passes
- Currently being worked on by @finalchild
- Migrate rustc_ast_passes diagnostics to
SessionDiagnostic
and translatable messages (first part) #100694 - [WIP] Migrate rustc_ast_passes diagnostics to SessionDiagnostic and translatable messages (second part) #101657
- Complete migrating
ast_passes
to derive diagnostics #108456
-
rustc_ast_pretty
-
rustc_attr
- Completed by @hampuslidin
- Migrate
rustc_attr
crate diagnostics #100836
-
rustc_borrowck
- Currently being worked on by @AndyJado
- migrate some
rustc_borrowck
diagnostic #100798 - Migrate more
rustc_borrowck
diagnostics toSessionDiagnostic
#100864 - Diag migrate #100871
- on
region_errors.rs
#100900 - Borrowck diag mig in one #101042
- region_name: remian a case #101305
mutability_errors.rs
diag-mig #101301Borrowck
: diag migrate #101276- [--bless] a Diagnotic Derive I wish to work for English words in
descr
#103469 - most
borrowck
diagnostic migration #101686 - Two mig-diag that fail ui test #101275
- first move on a nested span_label #103559
- piece of diagnostic migrate #103960
- Migrate diagnostics in
rustc_borrowck
#104055
-
rustc_builtin_macros
-
rustc_codegen_cranelift
- Blocked - hard to make the errors use the rustc infrastructure.
-
rustc_codegen_gcc
-
rustc_codegen_llvm
- Currently being worked on by @SLASHLogin
- Migrate rustc_codegen_llvm to SessionDiagnostics #101005
-
rustc_codegen_ssa
-
rustc_const_eval
- Currently being worked on by @fee1-dead
- Diagnostics migr const eval #100738
-
rustc_data_structures
-
rustc_driver
-
rustc_error_codes
-
rustc_error_messages
-
rustc_errors
- Available to be worked on!
- Move
IntoDiagnostic
conformance forTargetDataLayoutErrors
intorustc_errors
#102684
-
rustc_expand
- Currently being worked on by @tshepang
- Migrations for rustc_expand transcribe.rs #100651
- make "proc macro panicked" translatable #108436
-
rustc_feature
-
rustc_fs_util
-
rustc_graphviz
-
rustc_hir
-
rustc_hir_analysis
- Currently being worked on by @obeis
- Migrate
rustc_hir_analysis
to session diagnostic [Part One] #108434
-
rustc_hir_pretty
-
rustc_hir_typeck
-
rustc_incremental
- Completed by @davidtwco
- incremental: migrate diagnostics #100754
-
rustc_index
-
rustc_infer
-
rustc_interface
- Completed by @SkiFire13
- Migrate
rustc_interface
diagnostics #100808
-
rustc_lexer
-
rustc_lint
- Currently being worked on by @Rejyr
- Migrate
rustc_lint
errors toSessionDiagnostic
#100776 - Migrate
rustc_lint
lint diagnostics #101138
-
rustc_lint_defs
-
rustc_llvm
-
rustc_log
-
rustc_macros
-
rustc_metadata
- Completed by @CleanCut in Migrate rustc_metadata to SessionDiagnostics #100928
-
rustc_middle
- Available to work on!
- Migrate
rustc_middle
diagnostic #101021
-
rustc_mir_build
- Available to work on!
- Migrate
rustc_mir_build
diagnostics #100854 (continue from this partially completed work!)
-
rustc_mir_dataflow
-
rustc_monomorphize
- Completed by @CleanCut in Migrate rustc_monomorphize to use SessionDiagnostic #100730
-
rustc_parse
-
rustc_parse_format
-
rustc_passes
- Completed by @CleanCut, @rdvdev2 and @diegooliveira
- Migrate
rustc_passes
diagnostics #100870 - Migrate rustc_passes diagnostics #102110
- Migrated the rustc_passes annotation without effect diagnostic infrastructure #101815
- Migrate rustc_passes diagnostics #102110
- Port
dead_code
lints to be translatable. #103397
-
rustc_plugin_impl
-
rustc_privacy
- Completed by @davidtwco
- translation: lint fix + more migration #98420
-
rustc_query_impl
-
rustc_query_system
-
rustc_resolve
-
rustc_save_analysis
- Completed by @wonchulee in save_analysis: Migrate diagnostic #100780
-
rustc_serialize
-
rustc_session
- Completed by @luiscardosooliveira
- translations(rustc_session): migrates
rustc_session
to useSessionDiagnostic
- Pt. 1 #100753 101466 - translations(rustc_session): migrates rustc_session to use SessionDiagnostic - Pt. 2 #101041
- translations(rustc_session): migrates rustc_session to use SessionDiagnostic - Final #101266
-
rustc_smir
-
rustc_span
-
rustc_symbol_mangling
-
rustc_target
-
rustc_trait_selection::traits::error_reporting::suggestions
-
rustc_trait_selection
(everything else)- Available to work on!
- Porting 'compiler/rustc_trait_selection' to translatable diagnostics - Part 1 #100814
-
rustc_traits
-
rustc_transmute
-
rustc_ty_utils
-
rustc_type_ir
-
rustfmt
- Available to be worked on!
-
clippy
- Available to be worked on!
-
rustdoc
- Available to be worked on!-
Note: Some of these crates might not have diagnostics in them, in which case we'll just enable our internal lints on them. Some might have lots and lots of work that we can split up further, let us know! If there aren't many crates left, then feel free to leave a comment asking if someone is still working on their crate (check if they commented or have put a PR up recently).
Once you've picked a module (leave a comment letting us know!), how do you find the diagnostics to migrate? We've created rustc-internal lints that you can apply to a module which will produce an error for every diagnostic that hasn't been migrated.
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
(an example of using these would just be adding them to the top of a file)
After adding these attributes, you can run ./x.py check
to build the compiler in check mode (just like cargo check
in another project). You'll notice a bunch of errors that will look something like these:
error: diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls
--> compiler/rustc_parse/src/parser/mod.rs:1443:40
|
1443 | let mut err = sess.span_diagnostic.struct_span_err(
| ^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages
--> compiler/rustc_parse/src/parser/mod.rs:1443:40
|
1443 | let mut err = sess.span_diagnostic.struct_span_err(
| ^^^^^^^^^^^^^^^
There will be two errors for each diagnostic that isn't migrated:
- "diagnostics should be created using translatable messages"
- This error occurs when a diagnostic function is being invoked with something that isn't a translatable message (like a string literal or a formatted string).
- e.g.
err.label("an example label")
instead oferr.label(fluent::example_label)
fluent::example_label
corresponds to a message in a "Fluent resource" which we can provide different versions of for each language.
- e.g.
- This error occurs when a diagnostic function is being invoked with something that isn't a translatable message (like a string literal or a formatted string).
- "diagnostics should only be created in
Diagnostic
/Subdiagnostic
impls"- This error occurs when a diagnostic function is being called outside of an impl of
Diagnostic
orSubdiagnostic
. One of our goals with this migration is to move all diagnostic emission logic into impls on structs, as it helps keep the compiler tidy and works towards other goals of the diagnostics working group. - There are two ways to resolve this:
- Using a diagnostic derive to implement them automatically (preferred!)
- Implementing one of these traits (
Diagnostic
for errors and warnings,LintDiagnostic
for lints, orSubdiagnsostic
for parts of an error/warning/lint) manually.
- See "Migrate diagnostics" for more on these.
- This error occurs when a diagnostic function is being called outside of an impl of
We'll know we're finished when we can leave those attributes on every module in the compiler.
Migrate diagnostics
Okay, so you've got a diagnostic in front of you that you need to migrate.. now what?
- There's an introduction to performing a migration in the "Contribute to the diagnostic translation effort!" post on Inside Rust, this should serve as a decent introduction to the process.
- There's detailed documentation on diagnostic structs and on diagnostic translation in the developer guide that should be useful reference material.
- There are a lot of pull requests that perform migrations that you can dig through for examples, just look for pull requests labelled
A-translation
.
While migrating diagnostics, there might be cases you run into that we've not run across yet. Let us know in Zulip, you might be able to experiment and teach us how to translate some diagnostics, or there may be an opportunity to extend our core infrastructure (e.g. the derives). Don't worry though, you can always skip a diagnostic and leave it for someone else too.
Where to get help?
Discussion is primarily happening in the #i18n
stream on Zulip. Ask any questions you have in that chat and someone will try to help. If you don't get a response, feel free to ping @davidtwco
or @t-compiler/wg-diagnostics
.
One-off tasks
Sometimes there are one-off tasks which improve compiler infrastructure around translation or just make things easier to use, these are listed below, feel free to comment to take them:
Completed
-
Extendmacros: diagnostic derive on enums #102189SessionDiagnostic
derive to work on enums (context) -
In #100753, there are some functions annotated withlint: avoid linting diag functions with diag lints #101230#[rustc_lint_diagnostics]
which is used to know when to trigger our internal lints, that are themselves triggering the internal lint - it would be good to change the internal lint so that it skips functions annotated with#[rustc_lint_diagnostics]
. -
SupportDiagnostic derives: allow specifying multiple alternative suggestions #103209span_suggestions
-equivalent in diagnostic derives. -
errors: generate typed identifiers in each crate #103042 -
Diagnosticsicu4x
based list formatting. #104047
In-progress
To-do
- Diagnostic migration lints won't fire on diagnostics emitted in macros, this might be something we can improve (context)
- Adding support for
DefId
toSpan
conversions in the derive macros, e.g.#[primary_span(def_span)]
or something like that (context). - Better support for
Option<impl IntoDiagnosticArg>
(context) - Better support for
MultiSpan
(context). - Compile-time checks for unused Fluent messages (Unused Fluent messages lint #110754)
- Add a
IntoDiagnosticSpan
trait that can be implemented for anything usable with#[primary_span]
(i.e. so we can extend#[primary_span]
support toIdent
easily, for example) (partially complete at https://github.com/davidtwco/rust/tree/translation-into-diagnostic-span) - Add check for variables in Diagnostic #101109
- ICE when missing $ in front of a fluent variable #103539