Grails i18n из базы данных, но по умолчанию обратно в файл - PullRequest
11 голосов
/ 12 ноября 2011

После этой статьи блога Я включил свое приложение для загрузки сообщений 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 использует по умолчанию для просмотра источника.

ОБНОВЛЕНИЕ: благодаря doelleri я теперь понимаю, что мне нужно сделать что-то вроде расширения ResourceBundleMessageSource. К сожалению, есть несколько проблем с этим подходом. В моем файле resources.groovy есть следующее:

messageSource(DatabaseMessageSource)

Прежде всего, если я просто расширю ResourceBundleMessageSource и переопределю метод resolCode, этот метод никогда не будет вызван. Поэтому в моем блоке else вызов super.resolveCode является спорным.

Затем я попытался просто реализовать свой класс DatabaseMessageSource со всем кодом из ResourceBundleMessageSource, но я, очевидно, что-то упустил в resources.groovy, потому что пакеты по умолчанию не подключаются.

Так что на данный момент, я все еще потерялся в том, что мне нужно сделать. Я хочу сначала проверить базу данных. Если код не существует, вернитесь к тому же поведению по умолчанию, что и ResourceBundleMessageSource.

Ответы [ 5 ]

12 голосов
/ 20 ноября 2011

Я бы предложил сохранить один пакетный источник сообщений в новом бине и вставить его в ваш 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, иначе вы можете пропустить некоторые важные сообщения из ваших плагинов.

1 голос
/ 15 ноября 2011

Вместо этого вы можете расширить 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"
    }
 }
0 голосов
/ 22 ноября 2011

Я настоятельно рекомендую вам использовать 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, при первом использовании. Это действительно удобно.

Проверьте этооно того стоит.

0 голосов
/ 15 ноября 2011

Хотя это не является специфичным для Grails, мы в Griffon создали CompositeResourceBundle и DelegatingResourceBundle как части нашего собственного плагина i18n (источник, найденный в http://svn.codehaus.org/griffon/plugins/griffon-i18n/trunk/src/main/griffon/plugins/i18n/).

ExtendedResourceBundleMessageSource, показывает, как эти классы могут использоваться.

0 голосов
/ 14 ноября 2011

resolCode (code, locale) в AbstractMessageSource - это абстрактный метод, поэтому вы не сможете его вызвать. Попробуйте расширить ResourceBundleMessageSource или ReloadableResourceBundleMessageSource вместо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...