Grails:从 i18n 消息属性获取消息的首选方式

Grails: Most preferred way to get message from i18n message properties

我已经找到了一种从 i18n 消息属性(控制器外部)获取消息的方法

def messageSource = Holders.grailsApplication.mainContext.getBean 'messageSource'
....
errorMessages << [field: "transactionDate", message: messageSource.getMessage("transactionDate.require.message", null ,null)]

但后来在回顾我同事的作品时,我发现他们使用不同的方式..

def g = new ApplicationTagLib()
errorMessages.add([field: "exchangeRate", message: g.message(code: "exchangeRate.max.message")])

显然,这是一个更简单的版本,但我想知道首选哪种方式(最佳实践)以及两者之间的区别是什么。

Inside a Controller messageg.message 可直接从 ValidationTagLib 获得。您的同事正在将 ApplicationTagLib 的对象分配给变量 g。我怀疑 ApplicationTagLib 是自定义 class 而不是由 grails api 提供,至少在 2.3.x.

中没有

如果您在应用程序中除了控制器之外的任何地方都需要 i18 消息,那么您必须先获取 messageSource bean,或者您可以创建一个新的 ValidationTagLib 实例,然后调用 message() 在那个实例上。

作为对上述答案的补充,可能有以下地方需要实现国际化或从消息包中获取消息。

  1. 观看次数
  2. 控制器
  3. 服务
  4. 过滤器
  5. 实用程序文件(例如在 util 包或通用异常消息处理中)
  6. 特殊文件,例如在 Shiro 安全休息区

下面是详细的使用场景:

  1. 查看次数:- 我们有带有消息标签的标签库。在视图上使用它。

  2. controllers :- message 方法在此处默认可用,并且会自动处理语言环境转换。 See this.

  3. 服务:我们可以在服务内部调用标签库,如下所示:

    def myCustomTaglib = grailsApplication.mainContext.getBean('com.custom.MyCustomTagLib');
    

或者将 messageSource bean 注入为

def messageSource 
  1. 过滤器/实用程序/特殊文件:- 对于这些,您可以创建如下所示的内容,然后在整个过程中使用它。

    String i18nMessage(def input,String defaultMessage) {
        String[] languageCode = RequestContextHolder.currentRequestAttributes().request.getHeader("Accept-    Language").split("-")
        Locale locale = languageCode.length == 2 ? new Locale(languageCode[0], languageCode[1]) : new Locale(languageCode[0])
       String message = defaultMessage
       try {
            message = messageSource.getMessage(input.code,input?.args?.toArray(),locale)
        }catch (NoSuchMessageException nsme ){
            log.info("No such error message--> ${nsme.getMessage()}")
        }
       return message
     }
    

此外,如果您遇到以下异常:

java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

然后,您可能需要将请求侦听器添加到您的 web.xml

 <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
</listener>

注意: web.xml默认不可用,需要模板生成。

这些是您可能需要消息包转换的最常见位置。 第 4 点的解决方案几乎适用于所有情况。如果您注意到语言环境已在此处手动处理,我们可以在从 requestHeader 或可选的请求参数中获取后传递。

希望对您有所帮助。