Localizations (messages) plugin

  • Authors: Paul Fernley, Eamonn O'Connell
3 votes
Dependency:
compile ":localizations:1.4.4.14"

 Documentation  Source  Issues

Summary

This plugin will pull i18n definitions from the database rather than from the standard properties files in the i18n folder.

It will do the following:

  • Create a domain class and corresponding table called Localization
  • Prepopulate the table with all the message properties it finds in the i18n folder
  • Ensure Grails writes i18n messages based on what it finds in the database rather than the 118n folder
In addtion the plugin also has these added features to help you:
  • A CRUD UI to add, delete, and update i18n messages
  • A cache for increased speed
  • A JSONP action which can be useful in client-side templating.
Asumptions:
  • Your database supports unicode
  • Your application has a layout called main

Description

Localizations Plugin

Description

The localizations plugin alters Grails to use the database as its means of internationalization rather than message bundles (property files) in the i18n directory of your application. All property files in the i18n directory of your application (but not subdirectories of i18n) are automatically loaded in to the database the first time a message is requested after the plugin is installed. There is also an import facility (at a URL similar to http://myServer/myApp/localizations/imports) to load subsequently created property files - often the result of later installation of plugins. A 'message' method is added to all domain classes and service classes as a convenience. An 'errorMessage' method is added to all domain classes that can set an error message on either the domain as a whole or on a particular property of the domain. A localizations controller and CRUD screens are included with the plugin. The screens assume you are using a layout called main. Your database must be configured to allow the use of Unicode data for this plugin to work.

Installation

Execute the following from your application directory:

grails install-plugin localizations

The plugin creates one domain called Localization. It also copies a properties file called localizations.properties to the i18n directory of your application overwriting any file of the same name. When the plugin is first used, it will attempt to load the contents of any and all properties files in the i18n directory (but not subdirectories of i18n) of your application and load them in to the database. Per standard Grails, the files are read assuming UTF-8 encoding. After installation of the plugin, the Localization table in your database should have an index comprising of the two columns 'code' and 'loc' (which are a unique combination) but since Hibernate may or may not create this index, you are advised to check it exists otherwise performance may suffer. By default, the plugin uses a 'least recently used' cache for fast repeated access. The default maximum cache size is 128kb, but memory is only used as is needed. If you wish to alter the maximum size (amount of memory) used by the cache, you may do so by making an entry similar to the following in your Config.groovy file:

localizations.cache.size.kb = 512

The above example Config.groovy entry increases the cache size to 512kb. Setting the cache size to zero disables caching with a consequent increase in databases activity. You can check the cache statistics using a URL such as: http://myServer/myApp/localization/cache. Note that you may have to refresh your browser window to see the most up to date statistics.

Usage

The components of the plugin are in a package called org.grails.plugins.localization and any class that wishes to access the components directly must include the following:

import org.grails.plugins.localization.*

The localizations plugin adds a message method to each domain class and to each service class, for convenience. It also adds an errorMessage method to each domain class for setting either domain-wide or property-specific errors on the domain. These error messages are ususally displayed in a GSP using the normal <g:renderErrors.../> tag.

Messages

The following example can be used in a controller, a service, a domain class or a tag library (although you may preceed it with g. within a tag library). As you can see, it is a completely standard 'message' method call:

def msg = message(code: "my.code", args: [arg1, arg2],
                  default: "Missing message", encodeAs: "HTML")

Within a GSP you again use a completely standard message tag. For example:

<g:message code="my.code" args="${[arg1, arg2]}"
           default="Missing message" encodeAs="HTML"/>

All other internationalizations, such as select tags, renderErrors, flash messages etc should continue to work without change - except that their localized messages will now come from the database rather than message bundles.

Errors

Domain objects have an errorMessage method available which can set an error message either on the domain object as a whole, or on a specific property (field) within the domain object. The parameters to the errorMessage method are identical to those of the message method described previously. If you wish to make the error message specific to a field within the domain object, then an additional 'field' parameter is available. An example of setting a field error within a controller, might be as follows:

book.errorMessage(field: "title", code: "my.code", args: [arg1, arg2],
                  default: "Missing message")

An example of setting a domain-wide error message from within, say, the custom validator method of a domain class definition might be similar to the following:

… validator: {val, obj ->
        obj.errorMessage(code: "my.code", args: [arg1, arg2],
                         default: "Missing message")}

Note that the errorMessage method also returns the message it attached to the domain object, which can be useful for debugging and/or logging:

log.debug(book.errorMessage(code: "my.code"))

Imports

Although the localizations plugin automatically loads all data from the properties files in your i18n directory when it is first used after installation, you may subsequently add additional properties files (often by installing a plugin that has a properties file) that the localizations plugin will not know about. The localizations plugin comes with an imports screen that can be accessed by a URL such as http://myServer/myApp/localization/imports which will allow you to select a properties file from the i18n directory to import. Importing a file that has already been loaded in to the database will not overwrite texts for keys that already exist in the database but will add any keys that do not already exist in the database. This is done on the assumption that the database is the more up to date.

Note that the plugins mentioned in the Compatibility section below do not need to have their properties files (if any) imported even if you install them after the localizations plugin - they will detect this for themselves and auto-load their own properties file(s).

Limitations

Only 'base', 'language' and 'language and country' properties files are supported. That is to says properties files with 'variants' are not supported. For example: myBundle.properties, myBundle_es.properties, myBundle_es_ES.properties are all acceptable properties files but myBundle_es_ES_Traditional_WIN.properties is not since, in this example, it uses Traditional and WIN as variants.

If you distribute your finished application in the form of a war file, then unless the target application server unzips the war file on installation, the localizations plugin will be unable to automatically load (or subsequently 'import') the properties files from within the war file.

Compatibility

This plugin was written using Java version 1.6u18 and Grails version 1.3.0.

If you have the help-balloons plugin, on-screen help will be available when creating or editing localization records, otherwise you will have to read the help texts in the localizations.properties file to determine what is expected in each field. If you have the criteria plugin, the list page will allow selection criteria to be applied. It is strongly recommended that you use the criteria plugin since it makes locating particular keys and groups of keys so much more manageable. If you have the settings plugin installed and have created settings with keys of pagination.max and/or pagination.default then the localizations plugin will use those settings for its pagination. If you have the menus plugin installed, a 'return to menu' button will be placed after the 'home' button on all localization pages. The localizations plugin is also compatible with the drilldowns plugin, but the drilldowns plugin is not actually used by the screens in the localizations plugin.

History

Version 1.4.1 (2010-12-01) bugfix: reading properties files in deployed mode

Version 1.4. (2010-05-12) Update to Grails v1.3

Version 1.3. (2010-02-14) Update to Grails 1.2.1 plus fix for messages outside of requests, plus transactional message inserts

Version 1.2. (2009-12-30) Update to Grails 1.2

Version 1.1. (2009-02-01) Bug fix re invalid hierarchy use

Version 1.0. (2008-11-18) Initial release