2011-12-30 40 views
20

我已经使这个控制器,应该用来发送电子邮件。我需要访问i18n才能发送本地化的电子邮件。Grails:如何从控制器或服务访问i18n?

class MailController { 

    MessageSource messageSource 

    static transactional = false 

    public void sendEmail() { 
     String name = "some name..." 
     String subject = message(code:"somemessagekey", args:[name]) 
     // do some fancy stuff here... 
    } 
} 

还有就是国际化文件,然后(位于国际化文件夹):

file name: messages.properties 
content: somemessagekey = Blabla {0} - blablabla 

我跑在此之后,它会抛出(在集成测试):

groovy.lang.MissingPropertyException: No such property: messageSource for class: org.codehaus.groovy.grails.support.MockApplicationContext 

我出于想法如何处理控制器中的本地化(我也尝试过在服务中使用它,但这更加复杂)。

+0

并不需要调用g.message()? – 2012-01-01 06:13:50

+0

我为什么要这样做?我找不到有关“g”的信息。 – 2012-01-01 17:15:30

回答

22

如果您在使用Grails 1.3.7,你需要声明为消息源:

def messageSource 

这样,它会注入到你的控制器。我认为在2.0中,你可以按照你发布的方式来完成,但即使如此,我认为这是值得尝试的,如上所述。

+3

是的,帮助,谢谢。工作代码是:'def messageSource public void sendEmail(){ String subject = message(code:“somemessagekey”,args:[name])...' – 2012-01-01 17:20:20

5

在Grails的2.2.3它应该工作:

import org.springframework.context.MessageSource 
... 
def MessageSource messageSource 
... 
String subject = messageSource.getMessage("somemessagekey", [name], null) 
... 

参考链接和更多的可能性在这里:http://static.springsource.org/spring/docs/2.0.8/api/org/springframework/context/MessageSource.html

+3

不应该def MessageSource messageSource是MessageSource messageSource还是def messageSource?宣布def并且类是多余的。 – 2015-06-16 23:18:47

13

我知道有一个答案,但这里是我拿吧。我做了一个服务(由他人启发)

import org.springframework.web.servlet.i18n.SessionLocaleResolver 
import org.springframework.context.MessageSource 

class I18nService { 

    boolean transactional = false 

    SessionLocaleResolver localeResolver 
    MessageSource messageSource 

    /** 
    * 
    * @param msgKey 
    * @param defaultMessage default message to use if none is defined in the message source 
    * @param objs objects for use in the message 
    * @return 
    */ 
    def msg(String msgKey, String defaultMessage = null, List objs = null) { 

     def msg = messageSource.getMessage(msgKey,objs?.toArray(),defaultMessage,localeResolver.defaultLocale) 

     if (msg == null || msg == defaultMessage) { 
      log.warn("No i18n messages specified for msgKey: ${msgKey}") 
      msg = defaultMessage 
     } 

     return msg 
    } 

    /** 
    * Method to look like g.message 
    * @param args 
    * @return 
    */ 
    def message(Map args) { 
     return msg(args.code, args.default, args.attrs) 
    } 
} 

现在,在服务刚注入i18nService,你是好去!这也使得对其他服务的单元测试变得轻而易举,因为您可以模拟i18nService服务

作为奖励,服务将尝试为当前webrequest查找当前语言环境,并假定该服务在webrequest上下文中运行。

4

上面的答案并没有帮助我。 我使用的Grails 3.0.1及以下解决办法是让我

import org.springframework.context.i18n.LocaleContextHolder as LCH 
import grails.util.Holders; 

class MyService{ 

def messageSource = Holders.getGrailsApplication().getParentContext(); 

public String MyMethod() 
{ 
    String message = messageSource.getMessage("code",args,LCH.getLocale()); 
} 

} 
+0

如果您需要从另一个控制器调用控制器的方法,则messageSource将为空。 (至少对于我来说)。所以,自己设置它可能会很有趣。 – 2016-08-11 15:26:56

1

有用的正式方法其实很简单。 The official documentation规定如下:

很简单的控制器读取消息,因为你可以调用标签 的方法:

def show() { 
    def msg = message(code: "my.localized.content", args: ['Juan', 'lunes']) 
} 

同样的技术可以在tag libraries使用,但如果你的标签 库使用自定义namespace则必须与g.前缀通话 :

def myTag = { attrs, body -> 
    def msg = g.message(code: "my.localized.content", args: ['Juan', 'lunes']) 
} 

而且,请注意,当你的翻译不使用参数不提供ARGS:

def msg = message(code: "my.localized.content") 
+0

此答案仅适用于控制器。它在服务中不以这种方式工作。 – deflomu 2016-09-26 14:56:57

1

我使用Grails 3.x的注射messageSource

org.springframework.context.MessageSource

和使用

String getMessage(String code, Object[] args, String defaultMessage, Locale locale); 

这method.Modify你的代码

class MailController { 

    MessageSource messageSource 

    static transactional = false 

    public void sendEmail() { 
     String name = "some name..." 
     String subject = messageSource.getMessage('somemessagekey', [name], '', null) 
     // do some fancy stuff here... 
    } 
}