#error-message #error #message

i18n_error

i18n_error provides a convenient way to define and manage error messages with internationalization (i18n) support

1 unstable release

0.1.0 Jun 13, 2024

#135 in Internationalization (i18n)

MIT license

17KB
437 lines

I18nError for Rust

This library provides a convenient way to define and manage error messages with internationalization (i18n) support in Rust.

Installation

Add the following to your Cargo.toml:

[dependencies]
i18n_error = "0.1"
rust-i18n = "3"

Then, run cargo build to install the dependencies.

Example

use i18n_error::{I18nError, LanguageCode, ToI18nString};

#[macro_use]
extern crate rust_i18n;

rust_i18n::i18n!("locales");

#[derive(I18nError)]
#[i18n_language_codes(En, Fr)]
enum UseCaseError {
    #[i18n_key("error.UseCaseError.AuthorizationError")]
    Authorization,
    #[i18n_delegate]
    Domain(DomainError),
}


#[derive(I18nError)]
#[i18n_language_codes(En, Fr)]
enum DomainError {
    #[i18n_key("error.DomainError.ResourceNotFound")]
    ResourceNotFound,
}

fn main() {
    let error = UseCaseError::Authorization;
    assert_eq!(error.to_i18n_string(LanguageCode::En), "You do not have permission.".to_string());
    assert_eq!(error.to_i18n_string(LanguageCode::Fr), "Vous n'avez pas la permission.".to_string());

    let error = UseCaseError::Domain(DomainError::ResourceNotFound);
    assert_eq!(error.to_i18n_string(LanguageCode::En), "Resource not found.".to_string());
    assert_eq!(error.to_i18n_string(LanguageCode::Fr), "Ressource non trouvée.".to_string());
}
  1. i18n Preparation
    1. Create locales files in /locales directory. Refer to the rust-i18n for more details.
    2. Load rust-i18n in lib.rs or main.rs file.
  2. Define the Error Struct or Enum
    1. Use #[derive(I18nError)] to derive the necessary traits.
  3. Set the Language Codes
    1. Use #[i18n_language_codes(En, Fr)]. to specify the supported languages.
    2. LanguageCode based on ISO 639-1. Refer to the rust-i18n/LanguageCode for more details.
  4. Define the Error Variants
    1. Use #[i18n_key("{key of message in locale file}")] to map error variants to messages in the locale files.
    2. This allows error messages to be generated from the locale file.
  5. Delegating Error Message Generation
    1. If you want to delegate the generation of error messages to an inner error, use #[i18n_delegate].
    2. The inner error must also be defined with #[derive(I18nError)].
    3. This allows the error message to be generated from the inner error.

Details

Preparing Locale Files

I18nError relies on rust-i18n. You need to prepare your locale files in a format that conforms to rust-i18n standards. For more details, refer to the rust-i18n documentation.

In I18nError, locale files must be named using ISO 639-1 codes in lowercase. To support English and French, you need to create /locales/en.toml and /locales/fr.toml.

Generating Error Messages

The string specified with i18n_key corresponds to a YAML path in the locale file. For instance, if the key is error.UseCaseError.AuthorizationError, the structure of the locale file should be as follows:

"error":
  "UseCaseError":
    "AuthorizationError": "You do not have permission."

If the corresponding key does not exist in the locale file, the string {LanguageCode in lowercase}.{key} will be returned.

Delegating Message Generation

If an enum variant contains an error object, you can delegate the message generation to the inner error object by using the #[i18n_delegate] attribute. For example, in the UseCaseError::Domain variant, the message generation is delegated to DomainError because i18n_delegate is specified.

#[derive(I18nError)]
#[i18n_language_codes(En, Fr)]
enum UseCaseError {
    #[i18n_delegate]
    Domain(DomainError),
}

In this case, DomainError must derive I18nError.

#[derive(I18nError)]
#[i18n_language_codes(En, Fr)]
enum DomainError {
    #[i18n_key("error.DomainError.ResourceNotFound")]
    ResourceNotFound,
}

If DomainError does not derive I18nError, a compile error will occur.

enum DomainError {
    ResourceNotFound,
}

error[E0599]: no method named `to_i18n_string` found for reference `&DomainError` in the current scope
  --> src/lib.rs:28:14
   |
28 |     #[derive(I18nError)]
   |              ^^^^^^^^^ method not found in `&DomainError`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `to_i18n_string`, perhaps you need to implement it:
           candidate #1: `ToI18nString`
   = note: this error originates in the derive macro `I18nError` (in Nightly builds, run with -Z macro-backtrace for more info)

rustcE0599

License

This project is licensed under the MIT License.
For more information on the license, please see the license.

Dependencies

~290–760KB
~17K SLoC