Grails:如何从控制器或服务访问 i18n?

Posted

技术标签:

【中文标题】Grails:如何从控制器或服务访问 i18n?【英文标题】:Grails: How to access i18n from controller or service? 【发布时间】:2012-01-30 20:47:19 【问题描述】:

我做了这个控制器,应该用来发送电子邮件。我需要访问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...
    

然后有i18n 文件(位于i18n 文件夹中):

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

在我运行它之后,它会抛出(在集成测试中):

groovy.lang.MissingPropertyException:没有这样的属性:messageSource 类:org.codehaus.groovy.grails.support.MockApplicationContext

我不知道如何在控制器中处理本地化(我也在服务中尝试过,但这更复杂)。

【问题讨论】:

不需要调用 g.message() 吗? 我为什么要这样做?我没有找到关于“g”的信息。 【参考方案1】:

如果您使用的是 grails 1.3.7,则需要将消息源声明为:

def messageSource

这样它将被注入到您的控制器中。我认为在 2.0 中您可以按照您发布的方式进行操作,但即便如此,我认为还是值得尝试按照上述方式声明它。

【讨论】:

是的,这有帮助,谢谢。工作代码是:def messageSource public void sendEmail() String subject = message(code:"somemessagekey", args:[name]) ...【参考方案2】:

我知道有一个答案,但这是我的看法。我做了一项服务(受他人启发)

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 上下文中运行。

【讨论】:

【参考方案3】:

在 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

【讨论】:

def MessageSource messageSource 不应该是 MessageSource messageSource 还是 def messageSource?声明 def 和类是多余的。【参考方案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());



【讨论】:

如果你需要从另一个控制器调用一个控制器的方法,messageSource 将为空。 (至少对我来说)。所以,自己设置可能会很有趣。【参考方案5】:

官方的方式其实很简单。 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'])

另外,请注意当您的翻译不使用参数时不要提供参数:

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

【讨论】:

这个答案只对控制器有效。它在服务中不起作用。【参考方案6】:

我正在使用 grails 3.x.Injected messageSource

org.springframework.context.MessageSource

使用过

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

这个方法。修改你的代码为

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...
    

【讨论】:

【参考方案7】:

我尝试了下面的代码及其使用 Holders 的工作。

def messageSource = Holders.getGrailsApplication().getMainContext().getBean("messageSource")

String errorMesssage = messageSource.getMessage('validation.error.catalogue.not.found', null, messageSource.getMessage(
                        'validation.error.catalogue.not.found', null, 'No Content found for the Reserved Instance Plan Catalogue', locale), locale)

【讨论】:

以上是关于Grails:如何从控制器或服务访问 i18n?的主要内容,如果未能解决你的问题,请参考以下文章

服务中的 Grails 消息源错误

如何从 Grails 中的控制器访问域属性?

如何从 Grails 服务 (JPA + GAE) 中访问 EntityManager

您如何在 grails 2.3 中测试服务或控制器方法

如何从grails中的控制器调用服务

如何在 Grails 中显示异常?