add language selection cookie - fixes #352

Sat, 06 Jan 2024 20:31:14 +0100

author
Mike Becker <universe@uap-core.de>
date
Sat, 06 Jan 2024 20:31:14 +0100
changeset 298
1275eb652008
parent 296
355c86eaeca5
child 299
238de141d189

add language selection cookie - fixes #352

build.gradle.kts file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/AbstractServlet.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/servlet/LanguageServlet.kt file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/changelogs/changelog-de.jspf file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/changelogs/changelog.jspf file | annotate | diff | comparison | revisions
     1.1 --- a/build.gradle.kts	Fri Nov 24 00:07:36 2023 +0100
     1.2 +++ b/build.gradle.kts	Sat Jan 06 20:31:14 2024 +0100
     1.3 @@ -5,7 +5,7 @@
     1.4      war
     1.5  }
     1.6  group = "de.uapcore"
     1.7 -version = "1.2.1"
     1.8 +version = "1.2.2"
     1.9  
    1.10  repositories {
    1.11      mavenCentral()
    1.12 @@ -37,7 +37,7 @@
    1.13                  arrayOf(
    1.14                      "jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:3.0.0",
    1.15                      "org.glassfish.web:jakarta.servlet.jsp.jstl:3.0.1",
    1.16 -                    "org.postgresql:postgresql:42.6.0"
    1.17 +                    "org.postgresql:postgresql:42.7.1"
    1.18                  ).forEach {
    1.19                      if (libsAreProvided) compileOnly(it) else implementation(it)
    1.20                  }
     2.1 --- a/src/main/kotlin/de/uapcore/lightpit/AbstractServlet.kt	Fri Nov 24 00:07:36 2023 +0100
     2.2 +++ b/src/main/kotlin/de/uapcore/lightpit/AbstractServlet.kt	Sat Jan 06 20:31:14 2024 +0100
     2.3 @@ -28,6 +28,7 @@
     2.4  import de.uapcore.lightpit.DataSourceProvider.Companion.SC_ATTR_NAME
     2.5  import de.uapcore.lightpit.dao.DataAccessObject
     2.6  import de.uapcore.lightpit.dao.createDataAccessObject
     2.7 +import jakarta.servlet.http.Cookie
     2.8  import jakarta.servlet.http.HttpServlet
     2.9  import jakarta.servlet.http.HttpServletRequest
    2.10  import jakarta.servlet.http.HttpServletResponse
    2.11 @@ -35,6 +36,10 @@
    2.12  import java.util.*
    2.13  
    2.14  abstract class AbstractServlet : HttpServlet() {
    2.15 +
    2.16 +    companion object {
    2.17 +        const val LANGUAGE_COOKIE_NAME = "lpit_language"
    2.18 +    }
    2.19      
    2.20      protected val logger = MyLogger()
    2.21  
    2.22 @@ -100,22 +105,6 @@
    2.23          // the very first thing to do is to force UTF-8
    2.24          req.characterEncoding = "UTF-8"
    2.25  
    2.26 -        // choose the requested language as session language (if available) or fall back to english, otherwise
    2.27 -        if (session.getAttribute(Constants.SESSION_ATTR_LANGUAGE) == null) {
    2.28 -            val availableLanguages = availableLanguages()
    2.29 -            val reqLocale = req.locale
    2.30 -            val sessionLocale = if (availableLanguages.contains(reqLocale)) reqLocale else availableLanguages.first()
    2.31 -            session.setAttribute(Constants.SESSION_ATTR_LANGUAGE, sessionLocale)
    2.32 -            resp.locale = sessionLocale
    2.33 -            logger.debug(
    2.34 -                "Setting language for new session {0}: {1}", session.id, sessionLocale.displayLanguage
    2.35 -            )
    2.36 -        } else {
    2.37 -            val sessionLocale = session.getAttribute(Constants.SESSION_ATTR_LANGUAGE) as Locale
    2.38 -            resp.locale = sessionLocale
    2.39 -            logger.trace("Continuing session {0} with language {1}", session.id, sessionLocale)
    2.40 -        }
    2.41 -
    2.42          // set some internal request attributes
    2.43          val http = HttpRequest(req, resp)
    2.44          val fullPath = req.servletPath + Optional.ofNullable(req.pathInfo).orElse("")
    2.45 @@ -126,6 +115,29 @@
    2.46              req.setAttribute(Constants.REQ_ATTR_REFERER, it)
    2.47          }
    2.48  
    2.49 +        // choose the requested language as session language (if available)
    2.50 +        if (session.getAttribute(Constants.SESSION_ATTR_LANGUAGE) == null) {
    2.51 +            // language selection stored in cookie
    2.52 +            val cookieLocale = cookieLanguage(http)
    2.53 +
    2.54 +            // if no cookie, fall back to request locale a.k.a "Browser Language"
    2.55 +            val reqLocale = cookieLocale ?: req.locale
    2.56 +
    2.57 +            val availableLanguages = availableLanguages()
    2.58 +            val sessionLocale = if (availableLanguages.contains(reqLocale)) reqLocale else availableLanguages.first()
    2.59 +
    2.60 +            // select the language (this will also refresh the cookie max-age)
    2.61 +            selectLanguage(http, sessionLocale)
    2.62 +
    2.63 +            logger.debug(
    2.64 +                "Setting language for new session {0}: {1}", session.id, sessionLocale.displayLanguage
    2.65 +            )
    2.66 +        } else {
    2.67 +            val sessionLocale = session.getAttribute(Constants.SESSION_ATTR_LANGUAGE) as Locale
    2.68 +            resp.locale = sessionLocale
    2.69 +            logger.trace("Continuing session {0} with language {1}", session.id, sessionLocale)
    2.70 +        }
    2.71 +
    2.72          // if this is an error path, bypass the normal flow
    2.73          if (fullPath.startsWith("/error/")) {
    2.74              http.styleSheets = listOf("error")
    2.75 @@ -182,4 +194,23 @@
    2.76          return locales.ifEmpty { listOf(Locale.ENGLISH) }
    2.77      }
    2.78  
    2.79 +    private fun cookieLanguage(http: HttpRequest): Locale? =
    2.80 +        http.request.cookies?.firstOrNull { c -> c.name == LANGUAGE_COOKIE_NAME }
    2.81 +            ?.runCatching {Locale.forLanguageTag(this.value)}?.getOrNull()
    2.82 +
    2.83 +    protected fun selectLanguage(http: HttpRequest, locale: Locale) {
    2.84 +        http.response.locale = locale
    2.85 +        http.session.setAttribute(Constants.SESSION_ATTR_LANGUAGE, locale)
    2.86 +        // delete cookie if language selection matches request locale, otherwise set cookie
    2.87 +        val cookie = Cookie(LANGUAGE_COOKIE_NAME, "")
    2.88 +        cookie.isHttpOnly = true
    2.89 +        cookie.path = http.request.contextPath
    2.90 +        if (http.request.locale.language == locale.language) {
    2.91 +            cookie.maxAge = 0
    2.92 +        } else {
    2.93 +            cookie.value = locale.language
    2.94 +            cookie.maxAge = 2592000 // 30 days
    2.95 +        }
    2.96 +        http.response.addCookie(cookie)
    2.97 +    }
    2.98  }
     3.1 --- a/src/main/kotlin/de/uapcore/lightpit/servlet/LanguageServlet.kt	Fri Nov 24 00:07:36 2023 +0100
     3.2 +++ b/src/main/kotlin/de/uapcore/lightpit/servlet/LanguageServlet.kt	Sat Jan 06 20:31:14 2024 +0100
     3.3 @@ -58,8 +58,7 @@
     3.4          if (lang != null) {
     3.5              val locale = Locale.forLanguageTag(lang)
     3.6              if (!locale.language.isNullOrBlank()) {
     3.7 -                http.response.locale = locale
     3.8 -                http.session.setAttribute(Constants.SESSION_ATTR_LANGUAGE, locale)
     3.9 +                super.selectLanguage(http, locale)
    3.10              }
    3.11          }
    3.12  
     4.1 --- a/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf	Fri Nov 24 00:07:36 2023 +0100
     4.2 +++ b/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf	Sat Jan 06 20:31:14 2024 +0100
     4.3 @@ -24,6 +24,12 @@
     4.4    --%>
     4.5  <%@ page contentType="text/html;charset=UTF-8" %>
     4.6  
     4.7 +<h3>Version 1.2.2</h3>
     4.8 +
     4.9 +<ul>
    4.10 +    <li>Eine Ă„nderung der Sprache wird nun auch in einem Cookie gespeichert.</li>
    4.11 +</ul>
    4.12 +
    4.13  <h3>Version 1.2.1</h3>
    4.14  
    4.15  <ul>
     5.1 --- a/src/main/webapp/WEB-INF/changelogs/changelog.jspf	Fri Nov 24 00:07:36 2023 +0100
     5.2 +++ b/src/main/webapp/WEB-INF/changelogs/changelog.jspf	Sat Jan 06 20:31:14 2024 +0100
     5.3 @@ -24,6 +24,12 @@
     5.4    --%>
     5.5  <%@ page contentType="text/html;charset=UTF-8" %>
     5.6  
     5.7 +<h3>Version 1.2.2</h3>
     5.8 +
     5.9 +<ul>
    5.10 +    <li>Active language selection is now also stored in a cookie.</li>
    5.11 +</ul>
    5.12 +
    5.13  <h3>Version 1.2.1</h3>
    5.14  
    5.15  <ul>

mercurial