Multilingual Websites with Ruby on Rails (3)

Part 3 – Quality Assurence

Texte gehören zu den Teilen einer Anwendung, die häufig geändert werden. Wenn dann noch externe Übersetzer im Spiel sind, kann es leicht zu fehlenden Übersetzungen kommen

Wir möchten deshalb automatisch testen, dass es zu allen Texten in Sprache A auch Übersetzungen in Sprache B vorhanden sind. Ein solcher Test allein hilft schon sehr, und sollte ja nicht so schwierig sein.

Leider gibt es dabei eine Überraschung: in der Internationalisierung-API findet sich zur Zeit (Rails 2.3.5) keine Möglichkeit, alle Schlüssel aufzuzählen (sprich iterieren). Man muss also offenbar die Yaml-Dateien selbst einlesen, um an alle Schlüssel zu kommen. Unserer Test ist dabei leider abhängig von der konkreten Art der Datenhaltung.

texts_hash = YAML::load(IO.read('config/locales/de.yml'))

Wie haben nun einen rekursiven Hash. Um alle Schlüssel zu überprüfen, extrahieren wie sie mit einer gesonderten Funktion. Diese Funktion ist einfach rekursiv aufgebaut.

def deep_hash_key(hash, prefix)
  hash.keys.sort.collect{|key2|
    val = hash[key2]
    newprefix = prefix.nil? ? key2 : "#{prefix}.#{key2}"
    if val.is_a? Hash
     deep_hash_key(val, newprefix)
    else
      newprefix
    end
  }
end

Wollen wir jetzt die Übersetzungen für alle Schlüssel prüfen lauert die Zweite Falle: Wenn die Übersetzung eine Variableninterpolation enthält, erhalten wir einen Fehler beim Aufrufen der translate() Methode ohne den passenden Hash. Offenbar liefert uns die API auch keinen Zugriff auf den String ohne Interpolierung. Da uns in diesen Test nur die Existenz einer Übersetzung interessiert, und nicht ihr konkreter Wert, fangen wir die Exception “MissingInterpolationArgument” einfach auf.

Für eine deutsche Anwendung mit Übersetzungen in Englisch und Französisch sieht dann der Test so aus:

def test_all_texts_should_exists
  texts_hash = YAML::load(IO.read('config/locales/de.yml'))
  de_keys = deep_hash_key(texts_hash['de'], nil).flatten
  for lang in ['de', 'fr', 'en']
    I18n::locale = lang
    for key in de_keys
      begin
        val = I18n.translate(key, :default => nil, :raise => true)
      rescue I18n::MissingTranslationData
        val = nil
      rescue I18n::MissingInterpolationArgument
        val = true  # there was a value, only an argument is missing
      end
      assert_not_nil(val, "key missing for locale #{lang}: #{key}")
    end
  end
end

Wenn jetzt eine Übersetzung fehlt, liefert der Test eine Fehlermeldung der Art:

test_all_texts_should_exists(LocalisationTest): key missing for locale en: users.edit.title

Die fehlende Übersetzung können wir dann ergänzen, bevor wir eine neue Version der Anwendung veröffentlichen. Continue reading “Multilingual Websites with Ruby on Rails (3)”

Rotating Billboard with jQuery

Billboard with changing picturesIn 1998, I have presented “Meier’s billboard”, A virtual display panel with changing images. Technically it is a Java-applet. Unfortunately, the reputation of Java-applets in the browser was bad and there was not much interest in my Java-applets.

In the meantime, the networks became more powerful, the computers became faster, and thanks to CSS, we got new design elements. One day I was dealing with the JavaScript framework “jQuery”. I came across the animate()-method, and I wondered: “is it possible to realize the billboard only with JavaScript?”

Continue reading “Rotating Billboard with jQuery”

Multilingual Websites with Ruby on Rails (2)

Part 2 – Variables, Validations, Model Classes

Web pages often contains sentences in which a single word is changing. For example, “You are logged in as xxxx.” For the translation, we can obviously assemble the sentence from the components. There is often a problem, because the order of the words is different in different languages .

A better solution is the so-called interpolation, as Ruby itself also offers. The string contains a marked variable, which will be replaced at run time. The Yaml file specification does not use the Ruby syntax. Instead, you mark the variable with double curly brackets.

# Definition
  logmsg: "You are logged in as {{name}}."
 
# call
I18n.translate(:logmsg, :name => 'Administrator')
# or short form
t :logmsg, :name => 'Administrator'

Continue reading “Multilingual Websites with Ruby on Rails (2)”

SQL: Set a Field from a linked Table

A little hack for the Joomla Community Builder

Recently, I received a job request. An existing web application will be greatly expanded, and therfore converted to use the CMS “Joomla”. For the management of members  the extension “Community Builder” will be used.
Previously, users had a number as login name. This number should now be available in a field “member number” (german: mitgliedsnummer), and the numbers from existing users should be transferred. So much for the request from a customer perspective. Continue reading “SQL: Set a Field from a linked Table”

Multilingual Websites with Ruby on Rails

Part 1 – Overview

Writing software for several languages is an ever recurrent challenge. Ruby on Rails provides solutions to most of the standard problems in web development. But it needed time until the version 2.2. for the “Internationalization API ” to become an official part of Ruby on Rails. .

The Ruby-On-Rails Internationalization module

Continue reading “Multilingual Websites with Ruby on Rails”

Jad Check on the servers from Google

jad check service for online test of your jad files The Jad check is a quality assurance tool for providers of mobile Java software.

The check examines the so-called Jad file on frequently occurring errors. Some errors are otherwise very hard to find, so you save time during troubleshooting. Other errors leads to installation problems on only a few phones. According to Murphy Law, typically the phones of the most important customers. As a provider the test helps to avoid trouble and increases your customer satisfaction.

Continue reading “Jad Check on the servers from Google”