Статьи

Строительные леса Grails: enums и i18n

Функция скаффолдинга Grails является отличным ресурсом для быстрой генерации экранов создания / чтения / обновления / удаления (CRUD) для классов вашего домена. Создайте сущность, создайте контроллер и поместите статический каркас на вершину. Для различных типов свойств в вашем доменном классе используется подходящий (HTML) вход для ввода пользовательского ввода: логические значения становятся флажками, ассоциации с другими классами домена становятся (в зависимости от владения и ограничений), например, раскрывающимися списками или множественным выбором и т. Д.

Даже перечисление работает из коробки, как можно себе представить ? Этот пост служит небольшой подсказкой — в первую очередь для меня и других разработчиков, ищущих такого рода вещи — интернационализации экранов скаффолдинга в целом и перечислений в частности с использованием  toString () и SpringSourceResolvable .

Возьмите следующий продукт со статусом :

class Product {

	enum Status {
		AVAILABLE, SOLD_OUT
	}

	String name
	Status status

	static constraints = { name blank: false, unique: true }
}

class ProductController {

	def scaffold = true
}

Открытие нашего / product / create url покажет, что вы ожидаете.

Отличительной особенностью лесов является то, что интернационализация элементов на экране очень проста! Переводы по умолчанию для Home и Create уже предоставлены для дюжины или около того языков в папке i18n . Имя самого объекта («Продукт») и его свойства могут быть определены следующим соглашением: [имя объекта] .label и [имя объекта]. [Имя свойства] .label — см. Установку Grails / src / grails / Папка шаблонов / строительных лесов .

Посмотрите, как мы могли бы перевести несколько вещей на голландский, добавив несколько ключей к messages_nl.properties :

product.label=Product
product.name.label=Naam
product.status.label=Status

Если мы хотим протестировать определенный язык (без изменения среды вашего браузера) или вы просто хотите исправить приложение в определенной локали, мы можем переопределить локаль по умолчанию с помощью Spring глобально. Давайте сделаем это для голландского для следующих примеров.

beans = {

    localeResolver(org.springframework.web.servlet.i18n.FixedLocaleResolver) {
        defaultLocale = new Locale("nl", "NL")
    }
}

Повторное рассмотрение нашего экрана показывает нам правильные голландские переводы для элементов пользовательского интерфейса по умолчанию и для наших собственных свойств.

Пока все хорошо, но разве мы не хотели бы переводить значения для наших значений перечисления AVAILABLE и SOLD_OUT? Есть несколько подходов, которые мы можем предпринять, из которых я опишу toString () и использую SpringSourceResolvable .

# 1. нанизывать()

Как вы знаете, экраны scaffolded просто выводят значения в выборках и выпадающих списках с помощью метода toString () показанного объекта. Мы можем создать каждое перечисление с жестко закодированным переводом, и функция toString () вернет это значение.

class Product {

	enum Status {

		AVAILABLE("Beschikbaar"), SOLD_OUT("Uitverkocht")

		final String value
		Status(String value) {
			this.value = value
		}

		String toString() {
			value
		}
	}

	String name
	Status status

	static constraints = { name blank: false, unique: true }
}

И престо!

Фактические имена перечислений теперь появляются только в сгенерированном HTML:

<select name="status" required="" id="status" >
  <option value="AVAILABLE" >Beschikbaar</option>
  <option value="SOLD_OUT" >Uitverkocht</option>
</select>

# 2. MessageSourceResolvable

Теперь вы, вероятно, поймете, что вышеупомянутое жестко закодированное решение работает только для одного языка, одного жестко закодированного в самом enum — что вызовет проблемы, когда через месяц ваше приложение фактически должно будет поддерживать второй язык ? Итак, как мы используем тот факт, что у нас уже есть message_XX.properties, куда мы поместили другие наши ключи сообщений?

Используйте базовую среду Spring. Пусть наш enum реализует org.springframework.context.MessageSourceResolvable, например так:

	enum Status implements org.springframework.context.MessageSourceResolvable {

		AVAILABLE, SOLD_OUT

		public Object[] getArguments() { [] as Object[] }

		public String[] getCodes() { [ name() ] }

		public String getDefaultMessage() { "?-" + name() }
	}

Точно так же, как ошибки валидации — SpringError и ObjectError Spring, которые реализуют упомянутый интерфейс — мы можем предоставить наши собственные коды для поиска определенного ключа сообщения.

Просмотрев наш экран, вы заметите, что, поскольку мы еще не предоставили перевод, берется значение из getDefaultMessage () . Я просто добавил «? -» перед ним, чтобы сделать это более заметным, но вы можете делать все что угодно, например, просто возвращать name () .

Теперь мы можем предоставить значение в наших messages_nl.properties для каждого перечисления:

product.label=Product
product.name.label=Naam
product.status.label=Status
<b>AVAILABLE=Beschikbaar
SOLD_OUT=Uitverkocht</b>

И у нас тот же эффект, что и у нашей предыдущей жестко закодированной версии, но теперь мы сделали все правильно!

 Оригинальная статья:  http://tedvinke.wordpress.com/2012/08/22/grails-scaffolding-enums-and-i18n