After coding the app in English, I updated the language file (pt-BR.yml), the 'config/application.rb' (setting the default to pt-BR), and the 'inflections.rb'in order to have the error messages in my local language.
However, Rails now does not find my model because its logic does not pluralize in English anymore.
Is there a way to prevent Rails to use the local default language in models and controllers?
Or is there a better coding practice for it?
Thanks.
You can configure your inflections.rb rather than converting the default lang. You can do that like so:
ActiveSupport::Inflector.inflections(:es) do |inflect|
inflect.plural(/$/, 's')
inflect.plural(/([^aeéiou])$/i, '\1es')
inflect.plural(/([aeiou]s)$/i, '\1')
inflect.plural(/z$/i, 'ces')
inflect.plural(/á([sn])$/i, 'a\1es')
inflect.plural(/é([sn])$/i, 'e\1es')
inflect.plural(/í([sn])$/i, 'i\1es')
inflect.plural(/ó([sn])$/i, 'o\1es')
inflect.plural(/ú([sn])$/i, 'u\1es')
inflect.singular(/s$/, '')
inflect.singular(/es$/, '')
inflect.irregular('el', 'los')
end
Code taken from https://davidcel.is/posts/edge-rails-a-multilingual-inflector/
It looks like his gem also supports pt-BR https://github.com/davidcelis/inflections. I haven't personally tried it but it looks sane.
Related
Ruby on rails uses singular and plural conventions for model, view and controller names. This is very good, since one might have a model called user and a controller called users. This work with almost every word, such as user(s), tree(s), book(s), so every word that just has an s to form the plural.
However, what about words that do not just need an s to form the plural, such as words ending with the letter "y"? E.g., city and cities? Does rails know the difference or would I need to write city and citys, even though it is grammatically wrong?
Rails knows a lot of plurals. It can handle "city," for example:
1.9.2p318 :001 > "city".pluralize
=> "cities"
1.9.2p318 :002 > "cities".singular
=> "city"
However, you may find plurals it doesn't know, and won't be learning. See the documentation for ActiveSupport::Inflector
The Rails core team has stated patches for the inflections library
will not be accepted in order to avoid breaking legacy applications
which may be relying on errant inflections. If you discover an
incorrect inflection and require it for your application, you’ll need
to correct it yourself (explained below).
How do you correct it yourself? In config/initializers/inflections.rb. For example:
ActiveSupport::Inflector.inflections do |inflect|
inflect.plural /^(.*)(l)ens$/i, '\1\2enses'
end
See again the docs for ActiveSupport::Inflector for more on how to teach rails new inflections.
For a lot of common ones, it knows how to handle it pretty well. You can try this yourself in IRB by doing the following:
require 'active_support/all'
ActiveSupport::Inflector.pluralize("city")
And you'll get back a string with the value "cities". You can also add and adjust inflections by following the steps listed in config/initializers/inflections.rb
There's a config file config/initializers/inflections.rb that, as per this question lets you modify the puralization of certain items:
ruby on rails pluralization help?
However, I'm not interested in that. I want to turn the automatic modification of generated model names off.
Here's an example:
rails generate scaffold UserData data1:string data2:string
Data is changed to 'Datum':
%] cat app/models/user_datum.rb
class UserDatum < ActiveRecord::Base
attr_accessible :data1, :data2
end
This is undesirable behaviour.
How do I turn it off?
Specifically if you can please; I've seen a few threads with people saying things like 'you'll have to modify the recipe for that', but no actual guide to doing this.
(I appreciate people are going to want to start answering this with 'you should just stick to the rails way of doing things, there's a good reason for this and it'll work out in the long run'; please dont)
First of all, UserDatum is singular.
In any case:
Change your config/initializers/inflections.rb:
ActiveSupport::Inflector.inflections do |inflect|
inflect.uncountable %w(UserData)
end
(Use whatever naming convention you use, e.g., if you use underscores, user_data instead, or both.)
If you want to remove all pluralizations (sketchy: this will affect everything in the world):
ActiveSupport::Inflector.inflections do |inflect|
inflect.clear
inflect.singular(/$/i, '')
end
If you want to control only model/model file naming, patch ModelGenerator:
module Rails
module Generators
class ModelGenerator
def plural_name; singular_name; end
def plural_file_name; file_name; end
end
end
end
The best way of doing this is:
rails generate scaffold HouseData --force-plural
(it's still an item by item fix, but it doesn't mess around with the pluralization stuff, which is global and affects other parts of the app too)
I am defining some active records with acronyms. RvPark (Recreational Vehicle Park). When I titleize the class name, I get 'Rv Park'. It really should be 'RV Park'. Is there a good way to do this? Since this model shares code with other models, I need to create a generic solution, but I haven't been able to come up with one.
I did see a discussion on this, but there wasn't a solution that worked for me. any insight is appreciated.
https://rails.lighthouseapp.com/projects/8994/tickets/2944-titleize-doesnt-take-all-uppercase-words-into-account
You can do this by configuring ActiveSupport::Inflector, which provides the titleize method. Simply define your own inflections in an initializer.
# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections do |inflect|
inflect.acronym 'RV'
end
Restart your app to pick up the change. Now titleize knows how to handle "RV". Fire up a Rails console to check it out:
> "RvPark".titleize
=> "RV Park"
> "rv".titleize
=> "RV"
See the linked docs for more cool stuff you can do with inflections.
UPDATE: Acronym support was added to the Rails Inflector after I posted this.
See #Anson's answer for Rails 3.2 and up.
This looks like an edge-case that titleize wasn't designed for. The problem is the capitalize call inside will always turn RV into Rv.
I would create a generic name function for the models that call self.class.titleize internally, and then overload it in the RVPark model.
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
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!