Wenn man eine mehrsprachenfähige Webanwendung erstellen will, unterstützt Grails recht gut dabei. Man legt eine messages.properties-Datei (ein Message-Bundle) pro Sprache an und schreibt dort (wie in Java üblich) die Übersetzung von Schlüssel auf Text, so wie es auf der Grails-Website beschrieben ist. Die GSP-Seiten enthalten <g:message>-Tags zur Übersetzung.

Leider gab es bei mir ein Problem: Ich habe eine Grails-Anwendung mit einem deutschen und einem Default-Bundle, das englische Texte enthält und immer dann zum Zuge kommen soll, wenn die Sprache des Browser-Clients eben nicht Deutsch ist. Also:

  • messages_de.properties für Deutsch
  • messages.properties für alle anderen Sprachen

Ich stellte meinen Browser auf Deutsch ein – alles wunderbar, die deutschen Texte kamen einwandfrei. Ich stellte den Browser auf Englisch ein – Enttäuschung: es kamen immer noch deutsche Texte!

Nach einigem Suchen im Quellcode von Grails (ValidationTagLib.groovy) fand ich heraus, dass für die Übersetzung ein Objekt vom Typ ReloadableResourceBundleMessageSource aus dem Spring-Framework verantwortlich ist. Dieses hat eine Property fallbackToSystemLocale, die auf true oder false stehen kann. Sie steht standardmäßig auf true, das heißt, wenn kein Text für das eingestellte Locale gefunden wird, wird nicht etwa der Text aus dem Default-Bundle genommen, sondern noch einmal in demjenigen Message-Bundle gesucht, das dem „system locale“ entspricht. Meine Servermaschine läuft auch auf Deutsch, so dass nochmals auf die Texte in message_de.properties zugegriffen wurde.

Abhilfe:

Jetzt war klar, dass diese Property während der Initialisierung auf false gesetzt werden muss. Mit folgenden Zeilen in Boostrap.groovy war der Fehler behoben:

import org.codehaus.groovy.grails.commons.ApplicationAttributes  def init = { servletContext ->     def ctx = servletContext.getAttribute(ApplicationAttributes.APPLICATION_CONTEXT)     def messageSource = ctx.getBean("messageSource")     messageSource.fallbackToSystemLocale = false }

Wenn jetzt ein Request mit englischem Locale eintrifft, wird auf messages.properties zugegriffen, das ergibt das gewünschte Verhalten.