Over the past few years, Rust has gained in popularity as businesses increasingly look to promote their products and services on the world stage. According to Stack Overflow’s “2020 Developer Survey,” a whopping 86 percent of respondents who have used Rust plan to use it again, making Rust the most-loved programming language of 2020.
Internationalization (i18n) is a key consideration for companies planning to roll out their apps and software to a global audience. In this Rust internationalization tutorial, we’ll examine eight of the most popular Rust i18n crates and evaluate each for production-readiness and stability.
In this guide, we’ll look at eight of the most popular Rust internationalization crates and evaluate each for production-readiness and stability.
We’ll cover the following:
Internationalization is the process of developing content and applications that adapt to suit users from any region, language, or culture. In other words, internationalization is the process of making an app globally accessible by providing content that is appropriate for each region.
Internationalization is sometimes abbreviated as i18n because there are 18 letters between the initial “I” and the closing “N.”
Before we proceed with our Rust internationalization tutorial, let’s define some key terms:
In the era of static websites, localization is done by copying the whole site structure in multiple locales. Changes are made to each structure directly by the translator because each page is translated separately. Internationalization tools streamline this tedious, time-consuming, error-prone process.
Among Rust’s most enriching features is the language locale, which makes it easy to translate an app to various languages.
In general, there are three common localization systems:
Let’s examine each in more detail.
gettext is a localization system that separates translation files from the programming language and provides support for plural forms strings of any number. Sun Microsystems implemented the first version of gettext in 1993. In 1995, the GNU project released a free software implementation. Since then, gettext has been used by many programming languages, including Rust.
Here’s how to use gettext:
gettext(), _()
to accept translation strings in the source codexgettext
or other software to help keep track of translated string and the line on which gettext()/_()
was usedFluent is a translation system that focuses on producing natural-sounding translations by providing support for grammar expressions such as gender, plurals, conjugations, etc.
Fluent uses an expression from a file format called FTL (short for Fluent Translation List) to process translations. An FTL file represents a language that contains functions, attributes, variables, selectors, terms, etc. Each locale must have its own FTL file created in different locale directories with its own translations following the same syntax pattern.
# en-US # Simple variable text-layout = Fast track your productivity by testing out your code on the spot # Attributes form-layout = .button = Save and Execute .font-seletion = Font Size #es # Simple variable text-layout = Acelere su productividad probando su código en el lugar # Attributes form-layout = .button = Guardar y ejecutar .font-seletion = Tamaño de fuente
International Components for Unicode (ICU) is a standard encoding scheme that provides full-featured unicode services such as date manipulations, resource bundles for accessing localized information, character set conversion, etc. It provides conventional translation about the data expectation in the source message.
ICU depends on various data formats including XML, JSON, YAML, and properties files for message formatting and uses a message syntax that contains various standards including variables, select, pluralization, date, time, etc.
{ "text": "Just write text without any variables" } # Representing numbers { variableName, number, style }. { "amount" : "Your total is {total, number, ::currency/EUR}" } { "created_at": "The todo was posted on {publishedAt, date, medium} at {publishedAt, time, short}" } # Spanish version { "created_at": "La tarea fue publicada en {publishedAt, date, medium} a {publishedAt, time, short}" }
Let’s zoom in on eight of the most popular Rust internationalization APIs and compare their production-readiness, stability, and the overall developer experience.
Fluent is designed to improve the process of translation on platforms. It enables syntax operations, parsers, and core localization structs to use a low-level structure for formatting and storing messages in a single locale.
Fluent also provides an API that supports user-friendly helpers, framework binding, error fall-backing, language negotiation between user requested languages, resources, and input/output for processing selected resources.
Fluent LangNeg is based on fluent-langneg
, a JavaScript library implementation associated with Project Fluent, which was formerly called fluent-locale
. It uses unic-langid
and unic-locale
to retrieve and operate on locale identifiers. Fluent LangNeg also provides option for negotiating between different locales lists.
gettext
Rust gettext is based on GNU gettext, which is supported and modeled for vast number of languages such as php-gettext, gettext-go, js-gettext, and more. It stores the translated data in a .mo file, which is separated from the language files because it does not enforce directory structure for storage.
At the time of writing, this crate is still in the development stage.
gettext-rs
gettext-rs
uses the GNU Gettext FFI binding for Rust to build script execution based on environment variables. It currently has support for only Linux and Windows.
r_i18n
r_i18n
is a tool that translates string by accessing a string’s related key-value pair from the JSON file created for each languages in a configuration directory.
json-gettext
extracts strings from a JSON locale file to get a user’s catalog. The localization works by creating different JSON locales in a directory that has to be accessed by Rust.
json-gettext provides support for Rocket web framework and unic languid.
i18n_codegen
i18ncodegen is closely related to ri18n, which generates new code snippets based on the key-value pair specified in each JSON locale. The key in the JSON file becomes a method that can be accessed via implementation. This procedures is designed to help you avoid common bugs such as missing interpolations, i18n keys typos, etc.
rocket_i18n8
is designed to translate locale based on user request on rocket or actix web frameworks via i18n macro. Rocket I18N was built to support only compiled templates, such as the rcute and Askama template engines.
With these internationalization APIs, you can extend your business to other regional demographics, which could help boost overall user engagement with your Rust app.
The best internationalization tool to serve your needs will depend on your particular use case and what you hope to accomplish with your app. Some of the APIs mentioned above are more production-ready and stable than others, so make sure you do your homework before committing to a solution.
Debugging Rust applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking the performance of your Rust apps, automatically surfacing errors, and tracking slow network requests and load time, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your Rust application. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app’s performance, reporting metrics like client CPU load, client memory usage, and more.
Modernize how you debug your Rust apps — start monitoring for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.
One Reply to "Rust internationalization, localization, and translation"
Nice post! I’m glad this topic is getting some more publicity. Just a little shout out for some tools I’ve been developing to support localization in Rust https://github.com/kellpossible/cargo-i18n It is aimed both at libraries, providing an API for libraries to expose their localization capabilities, and end users localizing their binary projects and wanting to embed the localizations in the binary, and having the correct language detected and selected at runtime. There is support for fluent, and gettext at the moment. There is also a super handy macro to use with fluent projects to have your message keys checked at compile time. I plan to add support for more validations and any other localization system that has interest.