После некоторых исследований я пришел к следующему полному решению. Это плагин модуля, который будет динамически разрешать представление цели Result (проверено, работает на Scala 2.12.8 и Play 2.7.3):
package modules
import javax.inject.{ Inject, Provider, Singleton }
import play.api.Application
import play.api.i18n.Lang
import play.api.mvc.{ Result, Results }
import play.twirl.api.Html
/**
* The dynamic template loader module implementation.
* @param app the Play Application instance.
*/
@Singleton
class DynamicTemplateLoader @Inject() (app: Provider[Application]) {
import Results._
import reflect.runtime.universe._
/**
* Returns the dynamically resolved play Result corresponding to a view function name using Reflection.
*
* @param target the target view name, note it's the name only e.g. "index"
* @param args the formal arguments the view requires e.g. Seq(form, credentials)
* @param implicitArgs the implicit arguments that the view requires e.g. Seq(request, messages, webJarsUtil,
* assets, configuration)
* @param langOpt the language to default to, if the language is defined then it will branch to the specific language
* otherwise will omit the language.
* @return the dynamically resolved play Result corresponding to a view function name using Reflection.
*/
def resolve(target: String, args: Seq[Any], implicitArgs: Seq[Any])(implicit langOpt: Option[Lang]): Result = {
val loader = app.get().classloader
val currentMirror = runtimeMirror(loader)
val templateName = langOpt.map { lang => s"views.html.${lang.code}.$target" }.getOrElse(s"views.html.$target")
val moduleMirror = currentMirror.reflectModule(currentMirror.staticModule(templateName))
val methodSymbol = moduleMirror.symbol.typeSignature.decl(TermName("apply")).asMethod
val instanceMirror = currentMirror.reflect(moduleMirror.instance)
val methodMirror = instanceMirror.reflectMethod(methodSymbol)
val allArgs = args ++ implicitArgs
Ok(methodMirror.apply(allArgs: _*).asInstanceOf[Html])
}
}
Пример использования:
def doSomething() = Action { request =>
implicit val langOpt = Option(request.lang)
val target = "something"
val args = Seq(credentials) // e.g. user credentials
val implicitArgs = Seq(request, messages, webJarsUtil, assets, configuration)
Future.successful(dynamicTemplateLoader.resolve(target, args, implicitArgs))
}
и, наконец,образец views/en/something.scala.html
@import play.api.i18n.Messages
@import play.api.mvc.RequestHeader
@import org.webjars.play.WebJarsUtil
@import controllers.AssetsFinder
@import play.api.data._
@import play.api.Configuration
@(credentials: Credentials)(implicit request: RequestHeader, messages: Messages, webJarsUtil: WebJarsUtil, assets: AssetsFinder, configuration: Configuration) {
<div class="TODO">
<div>
}