Use Rails I18n for more than translations.
When developers think about Rails I18n, the first thing that comes to mind is typically translations. That’s definitely the core of the I18n API and it’s also baked right into Rails when it comes to several internal method calls, especially around time and date formats, making it easy to adapt for different languages.
However, the Rails I18n API is a powerful tool that extends beyond just converting text from one language to another. It provides a flexible way to manage configurations, dynamic content, and even multi-tenant logic in a structured manner.
In this blog post we'll explore how Rails I18n can be used beyond translations, using two practical examples.
Example 1: Dynamic Page Titles for Multi-Domain Applications
Imagine a Rails application serving multiple domains. To users, each domain appears as a unique website, but it's actually a single multi-site Rails app running the same logic under different domain scopes. While the views remain mostly identical, small elements like page titles and meta attributes need to vary by domain. Rather than creating multiple templates with helpers and partials, or hardcoding values in views and controllers, we can use Rails I18n to manage these differences dynamically.
Let's say our application internally maps the domains app1.com
and app2.com
to the Current Attributes object in Rails, so we can access the current “app” with Current.app
and get a return value of app1
or app2
. We'll use this to print out different page titles, even though the internal language stays the same:
# config/locales/en.yml
en:
page_title:
app1: "Hello from App1!"
app2: "Hello from App2!"
In our view template, all we need to do is pass in the right app identifier
<%= t(Current.app, scope: "page_title") %>
Now, our page titles will automatically adjust based on the accessed domain without requiring conditional logic scattered throughout our views.
Example 2: Namespace-Specific Status Descriptions
Another practical use case for Rails I18n is managing different status descriptions for the same state across different parts of your application. Consider an e-commerce platform where an order status needs to be displayed differently to administrators and customers.
# config/locales/en.yml
en:
order_status:
admin:
shipped: "Package dispatched"
customer:
shipped: "Your package is on its way!"
In your views or presenters, you can now use the appropriate namespace:
# Admin view
<%= t("order_status.admin.shipped") %>
# Customer view
<%= t("order_status.customer.shipped") %>
You could of course also combine this with passing in custom variables (think of order tracking number etc., which might only be needed for the admin part) into the translation call.
This approach provides several benefits:
- Keeps status messaging consistent across the application
- Centralizes all status-related content in one place
- Makes it easy to modify messaging without touching the application code
- Allows for different levels of detail based on the context
This pattern can be extended to handle various other scenarios where the same state needs different representations based on the context or user role.
Conclusion
Rails I18n is a powerful tool that goes beyond just translations. By using it for dynamic page titles in multi-domain applications or for other business-driven flows, we can simplify our codebase and keep configuration settings neatly organized. Gone are the cluttered if/else conditions or awkward helpers just to switch some string information. Get another valuable benefit is setting config.i18n.raise_on_missing_translations = true
in your development and test environments — this helps catch any missing translations early in the development process.