Developing a Rails app in a language other than english - ruby-on-rails

So I'm building a new rails app and it's end users will all be spanish speakers. I figured I should use rails' I18n API but it feels like this is meant for translating an app that's already written in english. What I mean by that is that internally rails looks things up (models, table names, routes) with the english locale. Thus it feels weird to name your models in spanish if they are not going to be pluralized correctly when creating the schema.
Anyone has best practices for this kind of situation? Should I just name everything in english and then map the translations on the es.yml file?

Even though the application should be viewed by spanish end users, you are probably better off coding it in english. This means writing english ruby code, english routes, english models etc. The only thing that should be spanish is the text on your web sites.
Some reasons:
All reserved words in ruby are english.
Libraries/Framework use english naming.
Pluralization etc. is in english.
Better chance of getting help on StackOverflow if the code snippet is in english.
You never know, maybe someday it will turn into a collaboration project with non spanish speaking developers.
As for the i18n api, you may skip using it for now if you only should present the site content in one language.

Write your code (and translation keys) in whatever language you prefer and use your es.yml for the translated language.
Here's an example of how you'd use I18n throughout your app:
app/controllers/things_controller.rb
def create
thing = Thing.new(params[:id])
if thing.save
redirect_to thing, notice: t('cosa.crear.prosperidad')
else
flash.now.alert = t('cosa.crear.fracaso')
end
end
app/views/things/index.html.erb
<h1><%= t('cosa.texto_de_ayuda') %></h1>
config/locales/es.yml
es:
cosa:
texto_de_ayuda: "Necesita ayuda para la creación de las cosas?"
crear:
prosperidad: "Cosa fue creado con éxito"
fracaso: "Hubo un problema al crear su cosa"

There's no golden rule, but I think code should be written in English (even if you start writing in Spanish you may mix Spanish and English words and make a mess in your code).
About the i18n, you should use it not only for translating your app from a language to another, but also to specify textual elements that will be shown to the user. Hence you can have all that content organized into an unique file. It's better for maintenance and code organization and you can specify the default language (.yml file) that Rails should use.

Related

How to selectively deactivate Rails I18n translation_missing spans?

In my Rails 5.2 app, almost all my UI, except the Admin area, is internationalized using t(). The "translation missing" spans often break the layout, but I figure that's a price worth paying in order to know when I may have misspelled a key or not committed a file or something. There is one place where the spans really don't work however, and that is when it comes to the self-described roles people have in my Groups. The roles can be pre-defined strings that are part of my en.yml, like "coordinator", "treasurer" and so on, but they can also be write-ins, like "minister of awesome". So doing t("groups.roles." + role) doesn't work because the "translation missing" span messes up the layout. This wasn't a problem in previous version of Rails because the "translation missing" spans were automatically disabled for the production environment and only the last part of the key was displayed, i.e. exactly the functionality I want here. In Rails 5.2 the spans also show up in production and this is a problem, at least for this part.
The functionality I'd really want, which used to be standard, is:
If the translation exists, display it.
If the translation doesn't exist, display the English string from en.yml (English is defined as a fallback language)
If the English doesn't exist either, display the final part of the key. With "translation missing" spans in development, without them in production.
I browsed all the answers on here about how to disable these error messages in production and the suggested solutions seem geared at Rails 4 or don't work. Or they have the side effect of deactivating fallback translations, which is an unacceptable trade-off for me because I need English fallbacks for much of my app. Overwriting or extending the TranslationHelper seems like a momentous task, especially since I'd only want the spans removed in production (like it used to work). So for my case and for now, I've decided against doing a complete override and I only changed the helper in the one place where I expect to have missing translations that are not a problem:
def human_role(role)
str = t("groups.roles." + role)
if str.include?("translation missing")
role
else
str
end
end
You can use :default option like this:
t("groups.roles.#{role}", default: role)
And if you want to have "translation missing" in development, without them in production (it's ugly a little):
t("groups.roles.#{role}", default: Rails.env.development? ? "#{role} translation missing" : role)

Rails 4.1 locale and 'version' based on url (.com, .cz, .de, etc)

Hope somebody can point me at the right direction with this...
Basically, i have the locales setup and it works fine. However, i need to depending on how the user gets to the site (example_company.com, example_company.cz or example_company.de..) have slightly different content(views and layout).
I've managed to boil it down to a constant or env variable that if i was to run multiple instances of the site(1 for each country), i could set on the server so that i get the behaviour i need with 1 code base.
My question is, how are people dealing with this in general? is there any way i can serve all countries on the same instance and set some flag based on .com or .cz or whatever, that dictates which 'version' they get without effecting the url itself?
I already have the locales in the url and would prefer not to mix the two as i will have to support multiple languages for each version. For example, french and czech would still support english.. But if i go to the french one, i will only show 2 locales (french and english)...
Hope i managed to explain properly.. if not let me know and i will try again.
If you use Rails' built-in i18n support, you can easily select locales by TLD.
From the official Rails i18n guide:
One option you have is to set the locale from the domain name where your application runs. For example, we want www.example.com to load the English (or default) locale, and www.example.es to load the Spanish locale. Thus the top-level domain name is used for locale setting. This has several advantages:
The locale is an obvious part of the URL.
People intuitively grasp in which language the content will be displayed.
It is very trivial to implement in Rails.
Search engines seem to like that content in different languages lives at different, inter-linked domains.
You can implement it like this in your ApplicationController:
before_action :set_locale
def set_locale
I18n.locale = extract_locale_from_tld || I18n.default_locale
end
# Get locale from top-level domain or return nil if such locale is not available
# You have to put something like:
# 127.0.0.1 application.com
# 127.0.0.1 application.it
# 127.0.0.1 application.pl
# in your /etc/hosts file to try this out locally
def extract_locale_from_tld
parsed_locale = request.host.split('.').last
I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
end
Be sure to read the i18n guide in full. It covers how to use the built-in i18n support. A big advantage is you don't need separate views for each locale.

Internationalization Best Practices / Rails App

I am new to ruby & rails and have started building an application.
My goal is to build this in a way I can easily translate the contents of the rails app and display the website contents in a locale preferred by registered user.
Appreciate any inputs on some of the best practices or references to any documentation to read, to build a web application that can be easily translated?
Thanks,
Krish.
Check out the Rails Internationalization (I18n) API. It does everything you've described.
Also check out Globalize3, it became a standard for model translations. Very useful.
You can use ready_for_i18n plugin that convert your erb to desired form.It saves some time.
You'd definetely watch this talk: http://www.youtube.com/watch?v=CTu4iHWGDyE
Here are some tips or best practices I noted while working through Internationalization of a Rails app. (It's possible that some of them are now outdated).
Before I get into a list here's some clarification between localization and translation that was helpful to me:
Definitions:
App localization and model translations are separate concerns. Figure out which one of those (or both) it is, that you need.
The way I use them here:
App localization: Localization your app to a locale.
Model translation: Translation your model/data into a language.
Example: Give me the french translation (model translation) of the resource in my Spanish site (app localization)
I use Globalize for model translations.
Helpful Tips/ Best Practices:
Some of the following are clearly just helpful tips while working in the Context of Rails + Globalize, some of them might be more than that... possibly best practices.
I18n.locale refers to and sets the locale of the app. When using Globalize, Globalize.locale refers to and sets the locale for model/data translations.
Set both I18n.locale and Globalize.locale on every request. Since these variables are set in Thread, it will avoid some hard-to-replicate bugs.
Set Globalize.locale to I18n.locale right after setting I18n.locale. This allows for model translations to default to the locale of the app. (On my Spanish site, I expect data to be in Spanish, by default).
Change Globalize.locale (and notI18n.locale) to change model translation.
Reset I18n.locale and Globalize.locale after every test. In rspec
RSpec.configure do |config|
config.after(:each) do
I18n.locale = :en
Globalize.locale = :en
end
end
Either use subdomain, or subfolder in the url to refer to the locale of the app.
Use a language parameter to specify the language of the data.
When you work on your rails app, you will probably use default_url_options to use I18n.locale as the default locale parameter for your route / path helpers. However this doesn't work in tests. I picked up a solution from this github issue on rspec-rails.
I monkey patch ActionDispatch::Routing::RouteSet like so:
class ActionDispatch::Routing::RouteSet
def url_for_with_locale_fix(options={})
url_for_without_locale_fix(options.merge(:locale => I18n.locale))
end
alias_method_chain :url_for, :locale_fix
end
Set up a translate helper t as a wrapper around the I18n.t method
module I18nHelper
def t string, options = {}
I18n.t string, options
end
end
RSpec.configure do |config|
config.include I18nHelper
end
This is mini-pattern I use. You can check it out: http://developers-note.blogspot.com/2012/01/rails-i18n-good-practice.html

Supporting different locale regions using Rails i18n

I'm using the standard Rails I18n API to localise some of our views. This is working really well, but we now have a few use cases for regional changes to the en locale.
The API guide mentions that this isn't supported directly, and other plugins should be used. However, I'm wondering whether there's a simpler way to do this.
I already have en.yml, so in theory I could just create en-AU.yml and en-US.yml which are effectively clones of en.yml but with a few regional changes applied. I could then add additional English - American and English - Australian options to our configuration which would map to the new region-specific locales and allow users to use a region-specific locale.
The only problem I can think of with this is that it isn't DRY -- I would have duplicate translations for all common English words. I can't see a way around this.
Are there any other disadvantages to this approach, or should I just bite the bullet and dive into one of the plug-ins such as Globalize2 instead?
The rails-i18n-translation-inheritance-helper is getting a bit old now, so here's my approach for a Rails 3.2 project.
If you keep both en-US and en-AU in the same en.yml file you can use the yml repeated node to have a super en section:
For example:
en: &en
errors:
messages:
expired: "has expired, please request a new one"
not_found: "not found"
en-US:
<<: *en
en-AU:
<<: *en
errors:
messages:
not_found: "tis not found"
I'm using translation inheritance helper plugin for this.
In newer versions of Rails/i18n, they've added a fallback feature. Works similar to the outdated translation inheritance helper gem
see this answer for more info: Fall back to default language if translation missing

Ruby On Rails: pluralize for other languages

I am building apps for a non-english audience. Right now, I use english nouns to name my models, yet I prefer to use native dutch ones. As the convention uses the plural of the class name for tables, I assume it is the pluralize method inside Rails (where it resides, I wouldn't know). How can I change the pluralize method and where is it located? Would this break Rails?
I am using Rails 2.3.5 and Ruby 1.8.7
Example:
The Book class becomes books now.
My Boek class becomes boeks, but it is grammatically correct to use boeken
Add your rules to an inflections.rb file in config/initializers. See the API documentation:
ActiveSupport::Inflector.inflections do |inflect|
inflect.plural 'boek', 'boeken'
end
Perhaps won't help you because you want Dutch language, but for Spanish, French, Kazakh, Turkish or Norwegian, there is this:
https://github.com/davidcelis/inflections
This is not answering the question specifically, but if a language has too much irregularities one can disable the inflector according to the discussion.
ActiveRecord::Base.pluralize_table_names = false
In addition, as far as views are concerned my preferred way of dealing with pluralizing foreign strings is i18n pluralization. Take a look at a straightforward example below.
# config/locales/en.yml
en:
message:
one: You have 1 message #Your foreign string
other: You have %{count} messages #Your foreign string
Then in view you can do
# app/views/messages/index.html.erb
<%= t("message", count: current_user.messages.count) %>
Check official documentation.
Hope that helps!

Resources