Wicket7:国际化和数据库访问



我想实现对wicket7应用程序的i18n支持。

要求:

  • 管理用户必须能够轻松编辑翻译
  • 翻译必须在不重新部署的情况下进行

我的实际做法是将翻译保存在数据库中。所有翻译都将被缓存。如果前端任务更改了翻译,则会更新缓存和数据库。到目前为止很容易。

事实上,我一直在替换页面中的翻译。一个可行的解决方案是在实现过程中加载每个翻译。这些翻译将设置在许多wicket元素中。我不喜欢这种方法,因为它会把代码(html+java)弄得一团糟。

我将尝试在我的实际方法中实现一个替换机制。页面呈现后,该机制将贯穿整个页面,并执行以下任务:

  1. 搜索所有占位符
  2. 加载占位符键的翻译(缓存)
  3. 用翻译替换占位符

这应该适用于正文和标题(站点标题)

下面是一个柳条模板的例子

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>${landingpage.site.title}</title>
</head>
<body>
<header wicket:id="headerPanel">header</header>
${welcome.message}
<footer wicket:id="footerPanel">footer</footer>
</body>
</html>

在这种情况下,应识别并替换${landingpage.site.title}和${welcome.message}。正如您所看到的,它是在模板中直接定义的,而不是在java代码中。这就是我想要实现的。

我希望我把要求说得足够清楚。如果没有,请不要介意发表评论。我会更新这个问题,让它更清楚。

我的方法是实现BasePage(扩展Page)并覆盖onAfterRender方法

@Override
protected void onAfterRender() {
super.onAfterRender();
Response originalResponse = RequestCycle.get().getResponse();
String updatedResponse = replaceWithTranslations(originalResponse);
originalResponse.reset();
originalResponse.write(updatedResponse);
}

方法replaceWithTranslations尚未实现,实际返回一个简单的String。该方法应该将originalRepsonse的输出流转换为String,搜索占位符并用db的值替换它们。

这种方法似乎有两个困难:

  • 我没有得到作为字符串的响应
  • 我得到了一个WicketRuntimeException(Page.java:666中的Page.checkRendering)

任何建议都会很棒!

好吧,问题似乎很简单。

幸运的是,这里有一个BufferedWebResponse。一个简单的演员阵容就可以了:

@Override
protected void onAfterRender() {
super.onAfterRender();
BufferedWebResponse originalResponse = (BufferedWebResponse) RequestCycle.get().getResponse();
String translatedResponse = replaceWithTranslations(originalResponse);
originalResponse.reset();
originalResponse.write(translatedResponse);
}
private String replaceWithTranslations(BufferedWebResponse originalResponse) {
String untranslatedText = originalResponse.getText().toString();
String translatedText = doTheTranslation(untranslatedText);
return translatedText;
}

受到@RobAu的启发,我给了三柱门i18n的机会。以下是我的想法:

模板:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><wicket:message key="landingpage.site.title">Site-Title</wicket:message></title>
</head>
<body>
<header wicket:id="headerPanel">header</header>
<wicket:message key="welcome.message">Welcome</wicket:message>
<footer wicket:id="footerPanel">footer</footer>
</body>
</html>

wicket:属性消息:

<input type="text" placeholder="username" wicket:message="placeholder:login.username"/>

IStringResourceLoader:

@org.springframework.stereotype.Component
public class I18NResourceLoader implements IStringResourceLoader {
@Autowired
private I18NCache i18nCache;
@Override
public String loadStringResource(final Class<?> clazz, final String key, final Locale locale, final String style, final String variation) {
return loadTranslation(key, locale);
}
@Override
public String loadStringResource(final Component component, final String key, final Locale locale, final String style, final String variation) {
return loadTranslation(key, locale);
}
private String loadTranslation(final String key, final Locale locale) {
final Optional<Translation> optional = i18nCache.get(key, locale);
if (!optional.isPresent()) {
return key;
}
return optional.get().getText();
}
}

Translation和I18NCache是自实现类。

最后是注册:

public abstract class BasePage extends WebPage {
@SpringBean
private I18NResourceLoader i18NResourceLoader;
public BasePage(){
addI18NResourceLoader();
...
}
private void addI18NResourceLoader() {
final List<IStringResourceLoader> resourceLoaders = Application.get().getResourceSettings().getStringResourceLoaders();
final boolean existsResourceLoader = resourceLoaders.stream()
.filter(p -> p instanceof I18NResourceLoader)
.collect(Collectors.counting()) > 0L;
if (!existsResourceLoader) {
resourceLoaders.add(i18NResourceLoader);
}
}
...
}

专业版:

  • Wicket的方法
  • RegEx更换处理没有问题
  • SPR

Con的

  • 模板感觉有点乱

实际上,我没有关于这种方法性能的信息。

出于两个原因,我决定保留在BasePage中添加ResourceLoader的逻辑。

  1. BasePage负责与页面表示有关的一切(弱原因:-)
  2. 我正在使用DI。如果我要在WebApplication中添加逻辑,我将不得不手动注入I18NResourceLoader或其依赖项

我认为您可以扩展IComponentResolver来替换像WicketMessageResolver这样的占位符。

最新更新