我正在努力将用户输入的数据国际化到一个相当大的客户端/服务器(HTTP(Hessian)用于通信)应用程序中,该应用程序存储在数据库中。用户可以选择他们想要查看的语言,并且在没有所请求语言的翻译时使用默认语言。
目前,数据类可能如下所示:
class MyDataClass {
private Long id;
private String someText;
/* getters and setters */
}
国际化后,它看起来像这样:
class MyDataClass {
private Long id;
private Set<LocalizedStrings> localizedStrings;
/* getters and setters */
}
class LocalizedStrings {
private Locale locale;
private String someText;
/* getters and setters */
}
当然,在MyDataClass中创建一个委托getter可能会很有趣,它负责以正确的语言环境获取文本:
public String getSomeText(Locale locale) {
for(LocalizedString localized : localizedStrings) {
if (localized.getLocale().equals(locale)) {
return localized.getSomeText();
}
}
}
在我的团队中,虽然需要一直传递语言环境直到他们到达数据类,但仍有一些问题。由于所有这些事情都发生在服务器上,并且每个对服务器的请求都是在专用线程中处理的,因此有人建议将请求的区域设置存储在ThreadLocal对象中并创建向后兼容的无参数getter:
public String getSomeText() {
return getSomeText(myThreadLocalLocale.get());
}
ThreadLocal然后需要是一个全局变量(静态某处)或者需要在每个单独的实例创建时注入到MyDataClass中(我们使用spring,所以如果我们对数据类进行Spring管理,我们可以注入它(对我来说感觉不对))。
对于语言环境使用ThreadLocal对我来说感觉不对。我可以模糊地说,我不喜欢getter中的隐形魔法和全局变量的依赖(在数据类中!)。然而,对此有一种“不好的感觉”并不是与同事争论它的好方法。为了帮助我需要以下其中一个答案:
答案 0 :(得分:2)
虽然,通常的做法是我不喜欢在应用程序中进行“深度”本地化。
Intead of this:
public String getSomeText() {
return getSomeText(myThreadLocalLocale.get());
}
我们这样做:
public LocalizableText getSomeText() {
return new LocalizableText(resourceBundle, "someText");
}
然后做,例如在JSP或输出层中:
<%= localizable.getString(locale) %>
逻辑本身与语言无关。我们的情况是,经过一些处理后,应用程序通过邮件发送结果,将其记录下来并以各种语言呈现给Web用户。因此,与结果生成和本地化一起处理必须是分开的。
答案 1 :(得分:1)
使用您描述的本地线程是Web应用程序中非常常见的模式。请参阅Spring API中的此类作为示例:
org.springframework.web.context.request.RequestContextHolder
使用servlet过滤器(或类似的)在本地线程中设置区域设置,然后在服务器完成每个请求后清除区域设置值。不要在每个地方注入它,而是使用类似于RequestContextHolder的静态工厂/访问器方法:RequestContextHolder.getRequestAttributes()。
答案 2 :(得分:1)
这种方法非常有效。 例如,Spring通过RequestContextListener和LocaleContextHolder使用ThreadLocal使Locale可用。
如果您创建自定义实现,请确保正确处理ThreadLocal(设置/删除)。
答案 3 :(得分:1)
ThreadLocal是不好的做法。它是全局变量,并且有很多关于任何语言有多糟糕的文章。 Spring使用它的事实并不能证明使用它。我喜欢cruftex给出的解决方案。避免通过全局变量传递数据。