首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >动态加载twirl模板

动态加载twirl模板
EN

Stack Overflow用户
提问于 2014-07-05 00:16:05
回答 2查看 2.5K关注 0票数 3

在我的Scala项目中,我使用了Twirl模板引擎。俄语和英语的模板文件结构是重复的,例如,我有以下两个路径:en.Send.txt.MonoEnsureru.Send.txt.MonoEnsure

在我的代码中,我希望能够动态加载enru模板,如下所示:

代码语言:javascript
复制
def render(lang: String) = lang.Send.txt.MonoEnsure("hi")
render("en") // does not work, just to illustrate my point

我如何才能做到这一点?

EN

回答 2

Stack Overflow用户

发布于 2014-07-09 18:51:57

这不是对你的问题的直接回答,而是解决你的问题的不同解决方案。另一个答案是如何在技术上实现你想要的东西,但是使用反射来做一些国际化是不必要的脆弱的,并且绝对不被推荐。

正如评论中提到的,当您在Play应用程序的上下文中使用Twirl时,Play为您提供了自己的国际化方式。因为你没有在你的应用程序中使用Play,所以你不能使用它。但是你不需要使用Play的特定方式来进行国际化。您可以轻松地构建自己的基本国际化构造,而无需引入额外的依赖项,我将在本答案中说明这一点。

首先也是最重要的,这种方法应该更加干练。其次,它将您的布局与您碰巧使用的语言解耦。最后,它是完全类型安全的,并且不使用反射。

首先,创建一个表示一种语言的类,包装一个Properties对象。

代码语言:javascript
复制
// Language.scala
class Language(filename: String) {
   val properties = new java.util.Properties()
   properties.loadFromXML(new FileInputStream(filename))

   def apply(key: String) = properties.getProperty(key, s"Key $key not found.")
}

object Language {
   val English = new Language("path/to/english.xml")
   val Russian = new Language("path/to/russian.xml")
}

还可以使用Properties XML format定义一些转换

代码语言:javascript
复制
<!-- path/to/english.xml -->
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
   <entry key="hello.world">Hello World</entry>
</properties>

<!-- path/to/russian.xml -->
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
   <entry key="hello.world">привет мир</entry>
</properties>

然后,在渲染时,您可以将正在使用的语言隐式地放在作用域上:

代码语言:javascript
复制
implicit val language: Language = determineLanguage() // Your logic for determining the language you want to use

// Do other things here..

// Render template
Send.txt.MonoEnsure("hi")

然后,在您的模板中,使用如下语言:

代码语言:javascript
复制
@(arg1: Any, arg2: Any)(implicit lang: Language)

<html>
   <body>
      <p>@lang("hello.world")</p>
   </body
</html>

它将输出一个显示"Hello World“或”приветмир“的页面,具体取决于所选择的语言。

Java:我的第一个建议是使用的默认属性文件格式,但事实证明它使用的是拉丁-1编码,不支持西里尔字符,这使得它很难与俄语一起使用。因此,我更新了我的答案,改为使用Properties XML格式(不幸的是更冗长),该格式使用UTF-8编码,因此支持西里尔字符。

票数 3
EN

Stack Overflow用户

发布于 2014-07-10 00:34:29

我认为这是应该实现这一点的代码:

代码语言:javascript
复制
import play.twirl.api.Template1

def getTemplate[T](name : String)(implicit man: Manifest[T]) : T =
  Class.forName(name + "$").getField("MODULE$").get(man.erasure).asInstanceOf[T]

def render(lang: String) = 
  getTemplate[Template1[String,String]](s"$lang.Send.txt.MonoEnsure").render("hi")

render("en")

模板被编译成BaseScalaTemplate,因此您可以使用反射来调用它。您只需要知道模板的参数数量,这样您就可以将其作为特征play.api.twirl.TemplateX的实例加载。在本例中为Template1[String, String] (第一个字符串用于参数,第二个字符串用于呈现响应的类型)。

有关scala How do I call a Scala Object method using reflection?中的反射的更多信息,请查看此线程

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24578073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档