#localization #documentation #translation #original #cargo #cargo-docs #doc-comment

app cargo-doc-l10n

A tool that bring to cargo support for localization of the documentation and help to maintain the localization in sync with the original documentation

2 releases

0.1.1 May 23, 2023
0.1.0 May 10, 2023

#153 in Internationalization (i18n)

MIT/Apache

36KB
516 lines

General

The cargo-doc-l10n tool allow to translate doc-comments used by rustdoc documentation and help to keep the translations as accurate as possible when the when original code evolve.

The main goals are :

  • Introduce a standard format for localization of doc-comments that feels natural for Rust developers.
  • The translation effort should have no impact for the developer(s) :
    • no change on the way to use doc-comments in the source code.
    • localization files are in a separate directory that developers don't have to care about.
    • they just have to use cargo doc-l10n instead of cargo doc to generate the localized documentations along the original one.
  • When the documentation is generated, you get a warning for the items whose translation is outdated or missing.
  • The translated documentation contain a warning and a reference to the current original text on items with an outdated translation.
  • A translator must be able to easily spot all the outdated translations.

How does it works

While the rustdoc tool get the documention text from the doc-comments in the source code (in the /src directory), the cargo-doc-l10n tool get the documentation text from doc-comments in files located in the /l10n/{lang}/doc/src that mimics original source files.

The tool help to keep these file consistent with the ones in the source

Guide

Install cargo-doc-l10n

Just run cargo install cargo-doc-l10n

Provide a translation for a new language

If you have a crate and you want to provide a translation of the documentation for a new language, run the following command at the root of the crate directory:

cargo doc-l10n add {lang}

where {lang} is the ISO-639-1 code for the language. It will create an set of files in the /l10n/{lang}/doc/src directory that match the files in the /src directory, but instead of regular source files with the .rs extension, there are localization files with the .loc.rs extension. These localization files are simili rust code that contains the declarations of the items documented in the matching rs file, but the doc-comments will contain the translation. The original doc-comment is preserved behind a tag (it will be useful to detect changes).

For example, the crate directory of a library localized in French and Spanish, with a single module named “my_mod”, should look like this :

+-src
| +-my_mod
| | +-mod.rs
| +-lib.rs
+-l10n
  +-es
  | +-doc
  |   +-src
  |     +-my_mod
  |     | +-mod.loc.rs
  |     +-lib.loc.rs
  +-fr
    +-doc
      +-src
        +-my_mod
        | +-mod.loc.rs
        +-lib.loc.rs

For every item documented in the original source code, the doc comment in the matching localization file will contains an empty line to be filled with the translation, followed by the content of the original doc-comment behind a [l10n] # (original) tagline.

For instance, given this src/lib.rs file in the original source:

/// The main struct of the library
struct MainStruct {
  /// The only field of MainStruct
  field : u32,
}

impl MainStruct {
  /// Do something interesting
  fn do_something(&mut self) {
    self.field += 1;
  }
  fn undocumented_fn(&self){
    println!("Hello World !"); 
  }
}

The generated /l10n/fr/doc/src/lib.loc.rs file for french localization will look like this :

///
///[l10n] # (original)
/// The main struct of the library
struct MainStruct {

  ///
  ///[l10n] # (original)
  /// The only field of MainStruct
  field : u32,
}

impl MainStruct {

  ///
  ///[l10n] # (original)
  /// Do something interesting
  fn do_something(&mut self) {}
}

You have to complete the empty space before the [l10n] # (original) with the translation for your language. Do not modify or removed the original section : it will be used to check if modification of the doc-comment in the source happend after its translation. Once you fill up the “lib.loc.rs” file, it should look like this :

/// La struct principale de la bibliothèque
///[l10n] # (original)
/// The main struct of the library
struct MainStruct {

  /// Le seul champ de la bibliothèque
  ///[l10n] # (original)
  /// The only field of MainStruct
  field : u32,
}

impl MainStruct {
 
  /// Fait quelquechose d'intéressant
  ///[l10n] # (original)
  /// Do something interesting
  fn do_something(&mut self) {}
}

Generating the translated documentation

When you run the cargo doc-l10n command, the documentation for all the available locales will be generated along the original one. If you want to generate the documentation only for one language, run cargo doc-l10n {lang} .

If an item documented on the source does not have a matching item in the localization files, or if the translation of the matching item is empty, you will get a warning on the command line about missing translation. The original text will be used for this item.

If an item documented on the source have a matching item in the localization files, but the doc-comment comment in the source does not contain the same text than the section behind the [l10n] # (original) line in the localization file, you will get a warning on the command line about outdated translation. The original text will be used for this item.

Fix an outdated translation

If changes happened on the source code and you want to fix the translation to match, run first the command cargo doc-l10n update {lang}. The content of the localization files for the specified language is automatically updated to match the new source and you will be warned on the command line about the parts of the localization files that need to be updated :

  • The items that were added to the source since the last translation, will be inserted into the ".loc.rs" files, with the usual empty part to be filled and the [l10n] # (original) section to keep unchanged.

  • For items whose doc-comment in the actual source does not match anymore the content behind the [l10n] # (original) line:

    • the previous translation is kept unchanged
    • there will be a [l10n] # (outdated) line. The section behind this line contains the previous original section.
    • the section behind [l10n] # (original) contains the new original doc-comment.

For instance if the previous lib.rs file is modified to :

/// The main struct of the library
struct MainStruct {

  /// The first field of MainStruct
  field : u32,
  
  /// An additional field
  additional_field : u32,
}

impl MainStruct {

  /// Do something interesting
  fn do_something(&mut self) {
    self.field += 1;
  }
  
  /// Do something else interesting
  fn do_something_else(&self){
    self.additional_field += 1;
  }
}

The updated “lib.loc.rs” will look like this :

///La struct principale de la bibliothèque
///[l10n] # (original)
///The main struct of the library
struct MainStruct {
  
  ///Le seul champ de la bibliothèque
  ///[l10n] # (outdated)
  ///The only field of MainStruct
  ///[l10n] # (original)
  ///The first field of MainStruct
  field : u32,
  
  ///
  ///[l10n] # (original)
  ///An additional field
  additional_field : u32,
}

impl MainStruct {
  /// Fait quelquechose d'intéressant
  ///[l10n] # (original)
  /// Do something interesting
}

Complete the empty parts with the translation.

Update the translations on items with the doc_outdated section. Then remove the doc_outdated section once you finished to fix the translation.

You can run again cargo doc-l10n update {lang} to check you have no warnings anymore.

Dependencies

~10MB
~233K SLoC