_('some text')
calls.Interface
Except the_(String)
method, there are several more standard methods to define messages for gettext. Generally there are two parts of them, for singular and plural forms. The first ones take as the main argument your usual message string, the second ones two more arguments, singular form of the message, plural form of the message and an optional number which helps to determinate when it is a singular form and when it is a plural form.Singular methods
String _(String)
- the standard method as we now it. The method takes a string and returns its translated version.String s_(String message[, String div="|"])
- this one for the cases when you need to define a scope for the message, say you have just the same message in two different context which might have different translation. So you write a string likes_('context|phrase')
, your message will be splat by the divider ('|' by default) and if there is no translation the last part of it will be returned. Simple examples_('gender|sex')
ands_('activity|sex')
, by default both of them will return 'sex', but you may have two different translations of the word in different languages depend on the context.String N_(String)
- this one might look a little bit strange. It tells gettext to define in its base the given string as a message, but does not translate anything and returns the given string as is. Generally it does just nothing, it is a dummy method and just a marker for the gettext parser. You will be given some examples of its usage below.
Plural methods
n_(String msg, String msg_plural, Integer number)
- this one is same as_(String)
but for the plural cases. The first argument is a singular version of the message the second is the plural version of the message. And the last argument the current lets call it plurality marker by which gettext will define which message use. NOTE: despite that you pass here only two messages, when you translate your .po files you may define several (more than two) translations of the messages which will depend on the plurality marker.ns_(String msg, String msg_plural, Integer number[, String div='|'])
- same ass_(String[, div])
but for plural formsNn_(String msg, String msg_plural)
- same as theN_(String)
method but for plural forms
That's all about the message definition methods.
Models Internationalization
GetText by default has all the standard error messages translations for most of the languages inside the package. And the parser will automatically define translations for your model fields which are in the database (meant field-names translation). So you don't need to worry about that.But sure you have got your special cases and you can follow the next instructions. Say the usual case, a user model where you have got some virtual fields
class User < ActiveRecord::Base
has_one :profile
has_many :comments
attr_accessor :password, :password_confirmation
# we can define the virtual fields translation like that
N_("User|Profile")
N_("User|Comments")
N_("User|Password")
N_("User|Password confirmation")
# we can create custom error-messages in this way
validates_uniqueness_of :login, :message => N_('The login-name is already taken')
def validate
errors.add("password", _("%{fn} is wrong!")) unless password == password_confirmation
end
end
As you see we have used the method
N_(String)
for class initialisation calls and the method _(String)
inside the custom validation method. The point is simple, in the first case you don't really need the translation result, you just need to define some messages and the second case works in runtime so you need an already translated version of the message.And another moment, we have used the 'User|' prefix in the field name definitions, this is to determinate in the translation which model the field name belongs, so you could have different translations of the field names for different models. By default it will be splat by '|' and the last token will be taken.
If you don't want to translate some particular field names, you may define to skip them by calling the
untranslate(*names)
method like that
class User < ActiveRecord::Base
untranslate :login, :email
# or
untranslate_all
end
Templates Internationalization
In most cases of templates internationalization you just use the standard gettext methods, like<%= _('Some label text') %>
, but there is another way.Sometime templates contain lots of text with big descriptions, so it is more comfortable to have another template file special for a particular language rather than put big pieces of text in the
_(String)
function. It is simple, just create another file next to existing one but with a name which have a suffix named after the locale you want. For example
app/views/pages/
about.html.erb
about_de_DE.html.erb
about_ru.html.erb
If the current locale is 'ru', then the
about_ru.html.erb
file will be used, if there is no matching file, the default about.html.erb
file will be used.Language Switching Tactics
And at the end some points about the language switching tactic. If you are experienced developer you probably do not need this part, but I would like to spell some words about it.The best way here I think is to follow the general ideology, separate parameter variables and the urls formatting, just as you do with say same ID parameter. A good solution would be define a parameter name which will point to the desired language, say
params[:lang]
, then as I showed in the previous article, you can use it in your application controller to switch the locale by a before filter.
class ApplicationController < ActionController::Base
init_gettext 'my_site'
before_filter :define_language
def define_language
case params[:lang]
when 'fr': set_locale 'fr_FR'
when 'ru': set_locale 'ru_RU'
else set_locale 'en_EN'
end
end
end
and then you left some options for youself how present it at your urls. You may use a simplest way like and left the gings as is
/articles/show/1 <- English
/articles/show/1?lang=fr <- French
or you can handle the language by routes so your pages were more caching friendly
map.connect ':controller/:action/:id'
map.connect ':lang/:controller/:action/:id',
:requirements => {
:lang => /(ru|de|fr)/
}, :lang => nil
----
/articles/show/1 <- English
/fr/articles/show/1 <- French
or later you may handle them by subdomains or something like that, whatever you choose your application code will not need changes.
--
Okay, think that is all what I had to say about using gettext with rails. Good luck!
1 comment:
Hello Nikolay,
good post. But what i still do not understand is, how i will be able to show translations to the user with
validates_uniqueness_of :login, :message => N_('user.login.alreadytaken')
With that i just see the string
'user.login.alreadytaken' on the page when this error occurs, but not any translated sentence, which i defined in my .po files.
You said N(string) actually does nothing. Ok, but i need a way to show the custom translated strings (set with :message) when validations fail.
Is there a way to do so with gettext, or is there some more work to do ? i have gettext 1.93.0 and rails 2.1.1
Thank you!
Regards
valley
Post a Comment