2011-11-11 7 views
11

seguito da this blog article Ho abilitato la mia applicazione a caricare i messaggi i18n dal database. Funziona alla grande. Tuttavia, non voglio gestire tutti i messaggi nel database. Quindi mi piacerebbe poter dire se non trovo il codice nel database, quindi caricarlo usando il meccanismo predefinito.Grail i18n dal database ma predefinito Torna al file

Ecco quello che ho:

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; 
    } 
} 

Ho provato a chiamare super.resolveCode (codice, locale), ma che ha portato in errori di compilazione. E sto facendo fatica a rintracciare l'implementazione di AbstractMessageSource che Grails sta usando per default per guardare la fonte.

AGGIORNAMENTO: Grazie a doelleri ora mi rendo conto che quello che devo fare è qualcosa come estendere ResourceBundleMessageSource. Sfortunatamente, ci sono diversi problemi con questo approccio. Ho il seguente nel mio file resources.groovy:

messageSource(DatabaseMessageSource) 

Prima di tutto, se ho semplicemente estendo ResourceBundleMessageSource e l'override del metodo resolveCode, tale metodo non viene mai chiamato. Quindi nel mio altro blocco, chiamare super.resolveCode è discutibile.

Ho quindi tentato di implementare la mia classe DatabaseMessageSource con tutto il codice da ResourceBundleMessageSource, ma apparentemente mi manca qualcosa in resources.groovy perché i bundle predefiniti non vengono cablati.

Quindi, a questo punto, sono ancora perso su quello che devo fare. Voglio prima controllare il database. Se il codice non esiste, ripristinare lo stesso comportamento predefinito di ResourceBundleMessageSource.

+0

Hai mai funzionato? – Marco

risposta

11

Vorrei proporre di mantenere una sorgente di messaggi bundle in un nuovo bean e iniettarla nel tuo 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; 
    } 
} 

In questo modo, in soluzione di ripiego, il messaggio verrà letto dal file appropriato messages_*.properties, semplicemente richiedendo da una risorsa sorgente del messaggio fascio. Nota che dovresti usare lo PluginAwareResourceBundleMessageSource, altrimenti potresti perdere alcuni messaggi importanti dai tuoi plugin.

0

resolveCode (code, locale) in AbstractMessageSource è un metodo astratto per cui non è possibile chiamarlo. Prova ad estendere ResourceBundleMessageSource o ReloadableResourceBundleMessageSource.

+0

Aha! Grazie. ResourceBundleMessageSource è probabilmente ciò di cui ho bisogno. Lo verificherò la mattina e riferirò. Molte grazie. – Gregg

+0

Come risulta, semplicemente l'estensione di ResourceBundleMessageSource non funziona. Il metodo resolveCode non viene mai chiamato e se provo a implementarlo nello stesso modo in cui è codificato nella classe effettiva (ho scaricato il codice sorgente) non viene cablato correttamente con tutte le informazioni del pacchetto in base a ciò che sto facendo nel file resources.groovy. Ho aggiornato la mia domanda per riflettere questo. – Gregg

0

Sebbene non sia specifico di Grails, noi di Griffon abbiamo creato CompositeResourceBundle e DelegatingResourceBundle come parti del nostro plug-in i18n (fonte trovata a http://svn.codehaus.org/griffon/plugins/griffon-i18n/trunk/src/main/griffon/plugins/i18n/).

ExtendedResourceBundleMessageSource mostra come è possibile utilizzare queste classi.

+0

Grazie aalmiray. Ho davvero bisogno di tornare di default a Spring/Grails il più possibile. Sembra che il codice stia gestendo il caricamento dei bundle da soli. Ho bisogno di Grails per caricare i bundle come li carica i grails. Devo solo aggiungere la possibilità di cercare prima nel database il messaggio. Forse sono solo troppo stanco in questo momento per averlo. Ma penso anche che il trucco risieda nel modo in cui definisco il mio bean in resources.groovy che probabilmente richiederà una risposta Grail. – Gregg

1

Si può estendere ReloadableResourceBundleMessageSource (l'originale pacco graal messaggio, che non sembra essere definitivo), invece, e quindi applicare questo codice:

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; 
    } 
} 

Si può anche riconfigurare le risorse del messaggio in Resources.groovy:

beans = { 
    messageSource(com.mycompany.DatabaseMessageSource) { 
     basename = "WEB-INF/grails-app/i18n/messages" 
    } 
} 
+0

No, l'utilizzo di ReloadableResourceBundleMessageSource non funziona. Non entra nemmeno nella mia classe DatabaseMessageSource dove ho impostato i breakpoint. E gli unici messaggi che vengono visualizzati sono i messaggi predefiniti forniti nell'utilizzo del messaggio taglib. – Gregg

+0

Immagino che in qualche modo il cablaggio in resources.groovy non sia buono, cioè non sovrascriva la configurazione predefinita del messaggio Source. Controlla anche la configurazione di resources.groovy, la mia configurazione originale era errata, cioè usa 'beans {..}' e non dimenticare com.mycompany .... o quale prefisso usi – fixitagain

+0

le notizie su questo problema? – fixitagain

0

Ti consiglio vivamente di utilizzare Copycopter (http://copycopter.com) per gestire il contenuto delle chiavi i18n. Permetterà al tuo team di aggiornare le chiavi al volo facilmente, usando un'interfaccia amichevole, e sarai in grado di impostare il valore predefinito come desiderato. In questo modo nessuno verrà da te quando una chiave deve essere aggiornata.

ThoughtBot, una forte società di consulenza per lo sviluppo web è dietro questo prodotto. È solido

Il codice sarà simile a questa, allora:

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}}) 

Le chiavi i18n sono generate al volo sul copytcopter, la prima volta che lo si utilizza. È veramente facile da usare

Controllalo, ne vale la pena.

+0

Perché hai fatto downvote? – Quentin