我已经找到了一种从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")])
显然,这是一个更简单的版本,但我想知道哪种方式是首选的(最佳实践),以及两者的区别是什么。
控制器内部message
和g.message
可直接从ValidationTagLib
获得。您的同事正在将一个对象ApplicationTagLib
分配给变量g
。我怀疑ApplicationTagLib
是一个自定义类,不是由grails api提供的,至少在2.3.x.中没有
如果您在应用程序中除了控制器之外的任何位置都需要i18消息,那么您必须首先获得messageSource
bean,或者您可以创建ValidationTagLib
的新实例,然后在该实例上调用message()
。
除了上述答案之外,您可能还需要在以下地方实现国际化或从消息包中获取消息。
- 视图
- 控制器
- 服务
- 过滤器
- 实用程序文件(例如,在util包或通用异常消息处理中)
- 特殊文件,例如Shiro安全休息区
以下是详细的使用场景:
-
视图:-我们有带消息标签的标签库。在视图中使用此选项。
-
controllers:-message方法在这里默认可用,并且自动处理区域设置转换。看看这个。
-
服务:我们可以在服务内部调用taglib,如下所示:
def myCustomTaglib = grailsApplication.mainContext.getBean('com.custom.MyCustomTagLib');
或者注入messageSource bean作为
def messageSource
过滤器/实用程序/特殊文件:-对于这些,你可以创建下面这样的东西,然后在整个过程中使用它。
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或request params获取后传递(可选)。
希望能有所帮助。