Grails i18n Из базы данных, но по умолчанию Back To File
После в этой статье в блоге Я включил мое приложение для загрузки сообщений i18n из базы данных. Он отлично работает. Однако я не хочу управлять всеми сообщениями в базе данных. Поэтому я хотел бы сказать, не найти код в базе данных, а затем загрузить его с использованием механизма по умолчанию.
Вот что у меня есть:
class DatabaseMessageSource extends AbstractMessageSource {
protected MessageFormat resolveCode(String code, Locale locale) {
Message msg = Message.findByCodeAndLocale(code, locale)
def format = null
if (msg) {
format = new MessageFormat(msg.text, msg.locale)
}else{
// What do I do here to grab it from the file
}
return format;
}
}
Я попытался вызвать super.resolveCode(код, локаль), но это привело к ошибкам компиляции. И я с трудом отслеживаю реализацию AbstractMessageSource, который Grails использует по умолчанию, чтобы посмотреть на источник.
UPDATE: Благодаря doelleri я теперь понимаю, что мне нужно сделать, это нечто вроде расширения ResourceBundleMessageSource. К сожалению, есть несколько проблем с этим подходом. В моем файле resources.groovy у меня есть следующее:
messageSource(DatabaseMessageSource)
Прежде всего, если я просто расширяю ResourceBundleMessageSource и переопределяю метод resolveCode, этот метод никогда не вызывается. Поэтому в моем блоке else вызов super.resolveCode является спорным.
Затем я попытался просто реализовать свой класс DatabaseMessageSource со всем кодом из ResourceBundleMessageSource, но я, очевидно, что-то пропустил в resource.groovy, потому что пакеты по умолчанию не подключаются.
Итак, в этот момент я все еще теряюсь в том, что мне нужно делать. Я хочу сначала проверить базу данных. Если код не существует, вернитесь к тому же поведению по умолчанию, что и ResourceBundleMessageSource.
Ответы
Ответ 1
Я бы предложил оставить один источник сообщений в новом bean и ввести его в DatabaseMessageSource
.
resources.groovy:
// Place your Spring DSL code here
beans = {
messageSource(DatabaseMessageSource) {
messageBundleMessageSource = ref("messageBundleMessageSource")
}
messageBundleMessageSource(org.codehaus.groovy.grails.context.support.PluginAwareResourceBundleMessageSource) {
basenames = "WEB-INF/grails-app/i18n/messages"
}
}
DatabaseMessageSource.groovy:
class DatabaseMessageSource extends AbstractMessageSource {
def messageBundleMessageSource
protected MessageFormat resolveCode(String code, Locale locale) {
Message msg = Message.findByCodeAndLocale(code, locale)
def format
if(msg) {
format = new MessageFormat(msg.text, msg.locale)
}
else {
format = messageBundleMessageSource.resolveCode(code, locale)
}
return format;
}
}
Таким образом, в резервном решении сообщение будет считано из соответствующего файла messages_*.properties
, просто запросив его из одного источника сообщений пакета ресурсов. Обратите внимание, что вы должны использовать PluginAwareResourceBundleMessageSource
, иначе вы могли бы пропустить некоторые важные сообщения из ваших плагинов.
Ответ 2
Вместо этого вы можете продлить ReloadableResourceBundleMessageSource (исходный комплект сообщений Grails, который не кажется окончательным), а затем применить этот код:
class DatabaseMessageSource extends ReloadableResourceBundleMessageSource {
protected MessageFormat resolveCode(String code, Locale locale) {
Message msg = Message.findByCodeAndLocale(code, locale)
def format = null
if (msg) {
format = new MessageFormat(msg.text, msg.locale)
}else{
format = super.resolveCode(code,locale)
}
return format;
}
}
Вы также можете перенастроить свои ресурсы сообщений в Resources.groovy:
beans = {
messageSource(com.mycompany.DatabaseMessageSource) {
basename = "WEB-INF/grails-app/i18n/messages"
}
}
Ответ 3
resolveCode (code, locale) в AbstractMessageSource - абстрактный метод, поэтому вы не сможете его назвать. Попробуйте расширить ResourceBundleMessageSource или ReloadableResourceBundleMessageSource вместо.
Ответ 4
Несмотря на то, что это не Grails, мы в Griffon создали CompositeResourceBundle и DelegatingResourceBundle как часть нашего собственного i18n-плагина (источник найден в http://svn.codehaus.org/griffon/plugins/griffon-i18n/trunk/src/main/griffon/plugins/i18n/).
ExtendedResourceBundleMessageSource показывает, как эти классы могут быть использованы.
Ответ 5
Я настоятельно рекомендую вам использовать Copycopter
(http://copycopter.com) для управления содержимым ключей i18n. Это позволит вашей команде легко обновлять ключи "на лету", используя дружественный интерфейс, и вы сможете установить по умолчанию по своему усмотрению. Таким образом, никто не придет к вам, когда нужно обновить ключ.
ThoughtBot, сильная консалтинговая компания по разработке веб-сайтов, стоит за этим продуктом. Он прочен.
Ваш код будет выглядеть следующим образом:
mail :to => member.email,
:subject => I18n.translate("member_mailer.reminder_to_sign_in.#{underscored_number_of_days}.subject",
:default => %{You have not signed in for #{humanized_number_of_days}})
Клавиши i18n генерируются "на лету" на copytcopter, при первом использовании. Это действительно легко использовать.
Проверьте это, это того стоит.