diff --git a/app/templating/I18hHelper.scala b/app/templating/I18hHelper.scala
index f05c4765e4..50bd89537f 100644
--- a/app/templating/I18hHelper.scala
+++ b/app/templating/I18hHelper.scala
@@ -1,15 +1,15 @@
package lila.app
package templating
+import scala.util.Random.shuffle
+
import controllers._
-import lila.user.Context
import lila.i18n.Env.{ current ⇒ i18nEnv }
import lila.i18n.{ LangList, I18nDomain }
-
+import lila.user.Context
import play.api.i18n.Lang
-import play.api.templates.Html
import play.api.mvc.{ RequestHeader, Call }
-import scala.util.Random.shuffle
+import play.api.templates.Html
trait I18nHelper {
@@ -38,7 +38,7 @@ trait I18nHelper {
def langLinks(lang: Lang)(implicit ctx: Context) = Html {
langLinksCache.getOrElseUpdate(lang.language, {
- pool.names.toList sortBy (_._1) collect {
+ pool.names.toList sortBy (_._1) map {
case (code, name) ⇒ """
%s""".format(
code,
langUrl(Lang(code))(I18nDomain(ctx.req.domain)),
@@ -48,11 +48,23 @@ trait I18nHelper {
}).replace(uriPlaceholder, ctx.req.uri)
}
+ def langFallbackLinks(implicit ctx: Context) = Html {
+ {
+ pool.preferredNames(ctx.req, 3) map {
+ case (code, name) ⇒ """%s""".format(
+ code, langUrl(Lang(code))(I18nDomain(ctx.req.domain)), name)
+ } mkString ""
+ }.replace(uriPlaceholder, ctx.req.uri)
+ }
+
def commonDomain(implicit ctx: Context): String =
I18nDomain(ctx.req.domain).commonDomain
- def acceptLanguages(implicit ctx: Context): String =
- ctx.req.acceptLanguages.map(_.language).distinct mkString ","
+ def acceptLanguages(implicit ctx: Context): List[String] =
+ ctx.req.acceptLanguages.map(_.language.toString).toList.distinct
+
+ def acceptsLanguage(lang: Lang)(implicit ctx: Context): Boolean =
+ ctx.req.acceptLanguages exists (_.language == lang.language)
private val uriPlaceholder = "[URI]"
diff --git a/app/views/base/layout.scala.html b/app/views/base/layout.scala.html
index 258dade18b..2509bbfd43 100644
--- a/app/views/base/layout.scala.html
+++ b/app/views/base/layout.scala.html
@@ -32,7 +32,7 @@ themepicker: Boolean = false)(body: Html)(implicit ctx: Context)
data-sound-file="@routes.Assets.at("sound/alert.ogg")"
data-troll="@ctx.troll.toString"
data-port="@netPort"
-data-accept-languages="@acceptLanguages">
+data-accept-languages="@acceptLanguages.mkString(",")">
@trans.freeOnlineChessGamePlayChessNowInACleanInterfaceNoRegistrationNoAdsNoPluginRequiredPlayChessWithComputerFriendsOrRandomOpponents()
@@ -102,7 +102,11 @@ data-accept-languages="@acceptLanguages">
lichess.org
+ @if(acceptsLanguage(lang)) {
@baseline
+ } else {
+ @langFallbackLinks
+ }
@menu.map { side =>
diff --git a/modules/i18n/src/main/I18nPool.scala b/modules/i18n/src/main/I18nPool.scala
index 91ad48774f..c52946f3c9 100644
--- a/modules/i18n/src/main/I18nPool.scala
+++ b/modules/i18n/src/main/I18nPool.scala
@@ -9,15 +9,19 @@ private[i18n] case class I18nPool(val langs: Set[Lang], val default: Lang) {
def nonDefaultLangs = langs - default
- val names: Map[String, String] = langs map { l ⇒
- l.language -> LangList.nameOrCode(l.language)
- } toMap
+ val names: Map[String, String] = (langs map langNames).toMap
+
+ private def langNames(lang: Lang): (String, String) =
+ lang.language -> LangList.nameOrCode(lang.language)
def lang(req: RequestHeader) = domainLang(req) | default
def preferred(req: RequestHeader) =
(req.acceptLanguages find langs.contains) | default
+ def preferredNames(req: RequestHeader, nb: Int): Seq[(String, String)] =
+ req.acceptLanguages filter langs.contains take nb map langNames
+
def domainLang(req: RequestHeader) =
cache.getOrElseUpdate(req.domain, {
I18nDomain(req.domain).lang filter langs.contains
diff --git a/public/javascripts/big.js b/public/javascripts/big.js
index ede863d8fb..4aa1fea799 100644
--- a/public/javascripts/big.js
+++ b/public/javascripts/big.js
@@ -602,9 +602,10 @@ var storage = {
});
});
+ var acceptLanguages = $('body').data('accept-languages').split(',');
$('#top .lichess_language').one('mouseover', function() {
var $t = $(this);
- _.each($('body').data('accept-languages').split(','), function(lang) {
+ _.each(acceptLanguages, function(lang) {
$t.find('a[lang="' + lang + '"]').addClass('accepted');
});
});
diff --git a/public/stylesheets/common.css b/public/stylesheets/common.css
index 6b019ceadb..ef24872d33 100644
--- a/public/stylesheets/common.css
+++ b/public/stylesheets/common.css
@@ -362,6 +362,11 @@ body.tight #site_header {
#site_header strong {
font-weight: normal;
}
+#site_header a.lang_fallback {
+ font-weight: bold;
+ display: inline-block;
+ margin-right: 1em;
+}
body > div.content {
width: 1005px;
min-height: 590px;