问题
The manual about i18n is short: https://www.playframework.com/documentation/2.4.x/ScalaI18N Is there anything more that explains the concept for handling the user's language choice?
What I'd like to achieve is what so many other sites do: put the language code into the URL
- http://namepedia.org/en/home/
- http://namepedia.org/de/home/
- ...
And then, when calling (Java) Lang.defaultLang().language()
or from a Scala template @lang.language
I'd like to get that value. Of course with the usual resolving, it must be in the application.conf play.i18n.langs = [ "en","de" ]
Do I really need to read it from the URL myself?
Also, in the routes file, isn't there a concept already for mapping it directly to the language resolving?
The alternative is to:
- duplicate all routes in the routes file per language, or use a regex for the lang code
- in each controller call a method for setting the language
回答1:
You can implement custom request handler and resolve language on every request. This is the same idea like your "in each controller call a method for setting the language" but you need to write the code only in one place - legacy GlobalSettings.onRequest
or new HttpRequestHandler.createAction
There is a very good description about realisation i18n in play based on the url part, the only one thing - it's for 2.0.4, so I suppose you would use HttpRequestHandler.createAction
but GlobalSettings.onRequest
.
Guide: http://www.flowstopper.org/2013/01/i18n-play-framework-java-app-website.html
Migration guide: https://www.playframework.com/documentation/2.4.x/GlobalSettings
Custom Request Handlers: https://www.playframework.com/documentation/2.4.x/JavaHttpRequestHandlers
Live examples from my project (Play 2.4.3, Java)
application.conf
play.i18n.langs = [ "en", "de", "fr", "ua" ]
play.http.requestHandler = "plugins.RequestHandler"
routes
# Home page
GET /$lang<[a-z]{2}>/home controllers.Application.home(lang:String)
plugins/RequestHandler.java
package plugins;
import play.http.DefaultHttpRequestHandler;
import play.libs.F;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.lang.reflect.Method;
public class RequestHandler extends DefaultHttpRequestHandler {
@Override
public Action createAction(Http.Request request, Method actionMethod) {
return new Action.Simple() {
@Override
public F.Promise<Result> call(Http.Context ctx) throws Throwable {
Path path = Paths.get(ctx.request().path());
String lang = path.getName(0).toString();
// we detect language only by URL path, cookies does not used
ctx.setTransientLang(lang);
return delegate.call(ctx);
}
};
}
}
controllers/Application.java
package controllers;
import play.*;
import play.mvc.*;
import play.i18n.Lang;
import views.html.*;
public class Application extends Controller {
public Result home(String lang){
return ok(ctx().lang().code());
}
}
This App would give results
http://localhost:9000/de/home -> "de"
http://localhost:9000/en/home -> "en"
http://localhost:9000/dk/home -> "exception: Language not supported in this application: Lang(dk,) not in Lang.availables()"
Take in to attention:
Lang.defaultLang().language()
will not return current request language. You need to call ctx().lang()
for returning current request language.
来源:https://stackoverflow.com/questions/32743911/play-framework-2-language-code-in-url-concept