【问题标题】:Wicket7: Internationalization and Database-AccessWicket7:国际化和数据库访问
【发布时间】:2017-01-08 10:24:12
【问题描述】:

我想为 wicket 7 应用程序实现 i18n 支持。

要求:

  • 翻译必须易于管理员用户编辑
  • 翻译必须在不重新部署的情况下进行

我的实际方法是将翻译保存在数据库中。所有翻译都将被缓存。如果前端任务更改了翻译,则缓存和数据库将被更新。 到目前为止一切顺利。

实际上,我一直在替换页面内的翻译。 一个可行的解决方案是在实施期间加载每个翻译。这些翻译将设置在许多检票口元素中。 我不喜欢这种方法,因为它会严重混淆代码(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(扩展页面)并覆盖onAfterRender-Method

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

replaceWithTranslations 方法尚未实现,实际上返回一个简单的字符串。此方法应将 originalRepsonse 的输出流转换为字符串,搜索占位符并将其替换为 db 的值。

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

  • 我没有收到字符串形式的响应
  • 我收到 WicketRuntimeException(Page.java:666 中的 Page.checkRendering)

任何建议都会很棒!

【问题讨论】:

  • 为什么不使用 Wicket 的 i18n 方法?与&lt;wicket:message&gt; 等? (见:ci.apache.org/projects/wicket/guide/7.x/guide/i18n.html
  • 第一次阅读这篇文章让我感到很生气。所有模板都与 混淆。并且只描述了本地化属性文件的使用。在其他网站上我读到:wicket 无法处理其他输入。现在我知道这些信息是垃圾。感谢您的建议!你能看看下面的解决方案,如果这是这样做的方法吗?

标签: java database internationalization wicket


【解决方案1】:

好的,问题似乎很简单。

诀窍还是运气,这里我们有一个 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;
}

【讨论】:

  • 您也可以为此使用org.apache.wicket.response.filter.IResponseFilter。它的目的正是为了在发送到浏览器之前对最终标记进行这种后处理。
【解决方案2】:

@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-Replacement-Handling 没有混乱
  • SPR

骗局

  • 模板感觉有点乱

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

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

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

【讨论】:

  • 干得好,迈克,你做对了。我同意&lt;wicket:message&gt; 有点笨拙。要确定性能是更好还是更差,您应该对其进行分析。它还取决于您的 replaceWithTranslations 实现。
  • 顺便说一句,我认为您现在每次构建页面时都添加i18NResourceLoader。您可以/应该将此逻辑移至 Application.init()
  • 哦,是的,你完全正确!我错过了这一点 :-) 这是一个真正的内存和性能泄漏。每个请求都会向数组添加一个 ResourceLoader。我会更新答案。非常感谢!
【解决方案3】:

我认为您可以扩展 IComponentResolver 以替换 WicketMessageResolver 等占位符。

【讨论】:

  • 您能再详细一点吗?我的研究提出了一个非常有用的链接。尤其是cmets。 sanityresort.blogspot.de/2011/08/…我会试一试。这是处理这类问题的检票口方式吗?
猜你喜欢
  • 2014-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多