Tuesday, September 25, 2007

Grails scaffolding templates improved; i18n aware templates available for download



Despite the fact that the Grails scaffolding templates can be customized, it has always bothered me that the "editors" in the create and edit views were fixed. This meant that tr, td and input elements could not be customized. In the current RC1 development snapshot the fixed code has been moved to a new template which can be customized when installing the templates.
[Note that the templates are still limited to list, create, edit and show views]

You can now customize the way various editors should be rendered, or maybe you want a complete different editor as used in the default templates. E.g. use the fancy Yahoo! UI Calendar instead of the default Grails datePicker.

Or use fully i18n aware templates which can be downloaded here. The i18n templates are now available by a new plugin: http://www.grails.org/I18n+Templates+Plugin. To use them, install the default templates in your project by running grails install-templates. This should create a folder \src\templates\scaffolding containing the default templates. Copy the downloaded templates in this folder and Grails will use them to generate a i18n aware application.

Here are some guidelines for resolving the i18n labels and messages for your domain classes. Imagine you application consists of these 2 domain classes:


class Author {
static hasMany = [books:Book]
String name

static constraints = {
name(blank: false, maxSize: 50)
}
}

class Book {
Author author
String isbn
String title
String category
Float price
String description

static constraints = {
author()
isbn(blank: false, maxSize: 10)
title(blank: false, maxSize: 50)
category(inList: ["Fantasy", "Mystery", "Romance", "Thriller"])
price(min: 0F, max: 100F, nullable: true)
description(blank: true, maxSize: 500)
}
}


Then by default the application is generated using the labels and messages as normal.
But you can change them by adding the following entries to your messages.properties:

# General messages
home=Home
list=List
new=New
create=Create
edit=Edit
update=Update
delete=Delete
delete.confirm=Are you sure?

# Author messages
author=Author
author.plural=Authors
author.created=Author {0} created
author.updated=Author {0} updated
author.deleted=Author {0} deleted
author.not.found=Author not found with ID {0}
author.id=ID
author.books=Books
author.name=Name

# Book messages
book=Book
book.plural=Books
book.created=Book {0} created
book.updated=Book {0} updated
book.deleted=Book {0} deleted
book.not.found=Book not found with ID {0}
book.id=ID
book.author=Author
book.isbn=ISBN
book.title=Title
book.category=Category
book.category.Fantasy=Fantasy
book.category.Mystery=Mystery
book.category.Romance=Romance
book.category.Thriller=Thriller
book.price=Price
book.description=Description

Off cource these English messages would not change anything, as the values would also be used as default. But you can now translate your complete application by just adding resource bundles for that language, and translating the properties.

Note that also the list constraint (by domain.property.value) is displaying i18n labels!

If I have time this week I might create a standalone plugin with these templates. This would include the general labels already then, and maybe some other useful features.

My end goal (and I'm thinking of this since I learned about Grails) is to have a 4GL-like application generator which uses it's own DSL to generate a Grails application. Think of defining number of rows to display in list, is insert allowed, is update allowed, etc.

4 comments:

Alexandre said...

and how I can do the database i18n,

ej:

table contents(
id
code
)

table i18Ncontents(
id
locale
description
)

Marcel Overdijk said...

Hi Alexandre,

The i18n plugin (part of Grails core) uses Spring's ReloadableResourceBundleMessageSource.

Spring does not offer a "DatabaseResourceBundleMessageSource" or something similar out of the box.

You need to write your own implementation for this.
Then you can use this implementation to define the messageSource in the applicationContext. It's all possible.

Alexandre said...

Is there some option like this
http://www.phpdoctrine.org/documentation/manual?chapter=plugins#internationalization-with-i18n:using-i18n
in grails?

Marcel Overdijk said...

I think it's possible why not.

It's just a matter of creating the needed domain classes (Newsletter and Translation) ane quering for the data.

Cheers and success,
Marcel