Saturday, July 26, 2008

Ubuntu HDTV fix

I had a problem with Ubuntu on my old notebook with Intel Mobile 915GM video-card. It didn't want to play hdtv files, rips and some .mkv files. It had been crashing with an insufficient resources error.

The issue is simple, the video card uses the system memory for its own purposes, and ubuntu has wrong default xorg configuration for the videocard. Add the following three lines to your /etc/X11/xorg.conf file into the Section "Device" section (search for the Driver "i810" line).

Option "VideoRam" "65536"
Option "CacheLines" "1980"
Option "LinearAlloc" "32768"

This will fix the problem.

Tuesday, July 22, 2008

TestCase 2.0.2 is out

TestCase - the kickass javascript testing framework has got new release with version 2.0.2

And I've launched the official support resource for the project, take a look, there is lot of interesting and useful stuff.

Sunday, July 20, 2008

Rails + Gettext Crash Course, Part 2

This is the second part of the first rails+gettext article. In this part we will take a look at some advanced points of using gettext and its bind to ruby/rails. Generally there is nothing "advanced", just say we move a little bit beyond elementary _('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 like s_('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 example s_('gender|sex') and s_('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 as s_(String[, div]) but for plural forms

  • Nn_(String msg, String msg_plural) - same as the N_(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!

Friday, July 18, 2008

Rails + Gettext Crash Course, Part 1

This article is a short guide to how use gettext with ruby-on-rails. If you do not know gettext is the standard internationalisation (i18n) library of the GNU project http://en.wikipedia.org/wiki/Gettext. And this is the first part of the two articles. The second one might be found here.

Since there are some of i18n plugins for rails why should you chose gettext?

For some reasons.

First as I said it is the standard for GNU. Standard means wide support several tools to work with it, optimisation, documentation, etc. Most of Linux programmes use gettext.

Second, one of the key features of gettext is ability to use real, correct strings. You don't write strange keys in your code, you just put usual English phrases instead, like that

<p><%= _('Some text here') %></p>
<p><%= _('Length: <i>(%{min} min)</i>') % { :min => @min_chars } %></p>

As you see this allows you easily use any placeholders or html formatting tags in here if you need so. Another point for gettext is that you don't have to keep in mind the translation issues during the development time. You just put your text as nothing happened and always have a default translation with normal usual looking strings.

After you have done with the development you can parse out all the strings which need to be translated with special util. You will have standard formed .po file which you can then translate with some special programs, where you can use spellchecking versioning and all the civilize life advantages.

Third, this stuff can do lots of things, localize numbers, dates, currencies, work with pluralization on native languages and so one. Take a look at the official site for getting more information http://www.gnu.org/software/gettext/gettext.html

So how do we use the stuff with rails?

Quite simple.

First of all you need to install gettext by itself and rubysupport aka gem. Installation of gettext depends on your platform. With linux it's pretty simple. Say something like

# emerge gettext
or
# apt-get install gettext

Once you have installed gettext support, you need to install the gettext gem.

# gem install gettext

After it is done, you need to include it into config/environment.rb file of your rails project.

require 'gettext/rails'

After this you can start develop your project and use the _('text') constructions where you need to put some text.

If you are using Rails 2.1, there's a bug which have not fixed yet. But you can easily fix it by saving the following code into a file config/initializers/gettext.rb

# the gettext missed method fix
module ActionView
class Base
delegate :file_exists?, :to => :finder unless respond_to?(:file_exists?)
end
end

Once you have done with the development and want to create some translation you need to do some preparations.

First you need to add two simple tasks to your Rakefile.

require 'gettext/utils'
desc "Update pot/po files to match new version."
task :updatepo do
GetText.update_pofiles(
"my_site",
Dir.glob("{app,lib}/**/*.{rb,rhtml,erb,rjs}"),
"my_site version"
)
end

desc "Create mo-files for L10n"
task :makemo do
GetText.create_mofiles(true, "po", "locale")
end

The first one will scan though your source code and parse out all the strings which need to be translated and put them all into a .po file. The second one will compile all your translations into a standard .mo files which gettext can use.

So, you say 'rake updatepo' in your console and this will create for you the file named 'po/my_site.pot', this is template of your internationalisation. You copy the file in translation directories like that.

po/
de_DE/my_site.po
fr_FR/my_site.po
ru_RU/my_site.po
my_site.pot

Then you translate the .po files with one of the translation programmes, say this one http://www.poedit.net. Under Linux and KDE you can use standard KBabel programme, or under Gnome you can use the gtrasnlator project. Certainly you can edit those files just as plain text if you like so. Many texteditors support them.

Once you have done with the translation, run the 'rake makemo' task in your console and it will create the 'locale' directory in your rails project folder with a standard structure like that

locale/
de_DE/LC_MESSAGES/my_site.mo
fr_FR/LC_MESSAGES/my_site.mo
ru_RU/LC_MESSAGES/my_site.mo

This is almost it. You only need to initiate it in your application controller now.

class ApplicationController < ActionController::Base
GetText.locale = 'en_EN' # <- default locale
init_gettext 'my_site'

before_filter :define_language

def define_language
# here you can switch the locale on fly
# say like that

case params[:lang]
when 'de': set_locale 'de_DE'
when 'fr': set_locale 'fr_FR'
when 'ru': set_locale 'ru_RU'
else set_locale 'en_EN'
end
end
end

As you see we have used non existing locale 'en_EN', if there is no some locale your default strings from the source code will be used. So you always have a fallback language.

This is pretty much it for the start.

But remember with gettext you not only put some translated text-labels in your application, you easily can create translations of whole template files, you can translate models, values, format numbers, dates and do lot of another useful things.

Thursday, July 3, 2008

TestCase 2.0 is out

After several month of development, finally I have released the tool version 2.0

There is the release notes and short changelog

Download page

And now you can watch the project's demo