You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by so...@apache.org on 2022/01/12 03:22:26 UTC
[wicket] branch wicket-9.x updated: [WICKET-6943] Save info about Locale direction LTR/RTL to Session metadata (#488)
This is an automated email from the ASF dual-hosted git repository.
solomax pushed a commit to branch wicket-9.x
in repository https://gitbox.apache.org/repos/asf/wicket.git
The following commit(s) were added to refs/heads/wicket-9.x by this push:
new 883f56d [WICKET-6943] Save info about Locale direction LTR/RTL to Session metadata (#488)
883f56d is described below
commit 883f56d3d9dda6e2932942c361f22d388fe8de96
Author: Maxim Solodovnik <so...@gmail.com>
AuthorDate: Wed Jan 12 10:09:27 2022 +0700
[WICKET-6943] Save info about Locale direction LTR/RTL to Session metadata (#488)
[WICKET-6943] Save info about language direction of session locale (RTL/LTR)
---
.../src/main/java/org/apache/wicket/Session.java | 55 ++++++++++++++++++++++
.../wicket/protocol/http/WebSessionTest.java | 55 +++++++++++++++++++++-
2 files changed, 109 insertions(+), 1 deletion(-)
diff --git a/wicket-core/src/main/java/org/apache/wicket/Session.java b/wicket-core/src/main/java/org/apache/wicket/Session.java
index c4152c9..3b389c4 100644
--- a/wicket-core/src/main/java/org/apache/wicket/Session.java
+++ b/wicket-core/src/main/java/org/apache/wicket/Session.java
@@ -27,6 +27,8 @@ import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
+import java.util.regex.Pattern;
+
import org.apache.wicket.application.IClassResolver;
import org.apache.wicket.authorization.IAuthorizationStrategy;
import org.apache.wicket.core.request.ClientInfo;
@@ -130,6 +132,15 @@ public abstract class Session implements IClusterable, IEventSink, IMetadataCont
/** Name of session attribute under which this session is stored */
public static final String SESSION_ATTRIBUTE_NAME = "session";
+ /**
+ * taken from Google Closure Templates BidiUtils
+ *
+ * A regular expression for matching right-to-left language codes. See
+ * {@link #isRtlLanguage} for the design.
+ */
+ private static final Pattern RTL_LOCALE_RE = Pattern.compile("^(ar|dv|he|iw|fa|nqo|ps|sd|ug|ur|yi|.*[-_](Arab|Hebr|Thaa|Nkoo|Tfng))"
+ + "(?!.*[-_](Latn|Cyrl)($|-|_))($|-|_)");
+
/** a sequence used for whenever something session-specific needs a unique value */
private final AtomicInteger sequence = new AtomicInteger(1);
@@ -185,6 +196,36 @@ public abstract class Session implements IClusterable, IEventSink, IMetadataCont
}
/**
+ * Check if a BCP 47 / III language code indicates an RTL (right-to-left) language, i.e.
+ * either: - a language code explicitly specifying one of the right-to-left
+ * scripts, e.g. "az-Arab", or
+ * <p>
+ * - a language code specifying one of the languages normally written in a
+ * right-to-left script, e.g. "fa" (Farsi), except ones explicitly
+ * specifying Latin or Cyrillic script (which are the usual LTR (left-to-right)
+ * alternatives).
+ * <p>
+ * <a href="http://www.unicode.org/iso15924/iso15924-num.html">
+ * The list of right-to-left scripts appears in the 100-199 range in</a>, of which Arabic and
+ * Hebrew are by far the most widely used. We also recognize Thaana, N'Ko,
+ * and Tifinagh, which also have significant modern usage. The rest (Syriac,
+ * Samaritan, Mandaic, etc.) seem to have extremely limited or no modern
+ * usage and are not recognized. The languages usually written in a
+ * right-to-left script are taken as those with
+ * <a href="http://www.iana.org/assignments/language-subtag-registry">Suppress-Script</a>:
+ * Hebr|Arab|Thaa|Nkoo|Tfng, as well as
+ * Sindhi (sd) and Uyghur (ug). The presence of other subtags of the
+ * language code, e.g. regions like EG (Egypt), is ignored.
+ *
+ * @param locale - locale to check
+ * @return <code>true</code> in case passed locale is right-to-left
+ */
+ private static boolean isRtlLanguage(final Locale locale) {
+ Args.notNull(locale, "locale");
+ return RTL_LOCALE_RE.matcher(locale.toLanguageTag()).find();
+ }
+
+ /**
* Cached instance of agent info which is typically designated by calling
* {@link Session#getClientInfo()}.
*/
@@ -202,6 +243,9 @@ public abstract class Session implements IClusterable, IEventSink, IMetadataCont
/** The locale to use when loading resources for this session. */
private final AtomicReference<Locale> locale;
+ /** True if locale's language is RTL (right-to-left) */
+ private boolean rtlLocale = false;
+
/** Session level meta data. */
private MetaDataEntry<?>[] metaData;
@@ -240,6 +284,7 @@ public abstract class Session implements IClusterable, IEventSink, IMetadataCont
"Request#getLocale() cannot return null, request has to have a locale set on it");
}
this.locale = new AtomicReference<>(locale);
+ rtlLocale = isRtlLanguage(locale);
pageAccessSynchronizer = new PageAccessSynchronizerProvider();
}
@@ -606,12 +651,22 @@ public abstract class Session implements IClusterable, IEventSink, IMetadataCont
if (!Objects.equal(getLocale(), locale))
{
this.locale.set(locale);
+ rtlLocale = isRtlLanguage(locale);
dirty();
}
return this;
}
/**
+ * Method to determine if language of current locale is RTL (right-to-left) or not
+ *
+ * @return <code>true</code> if language of session locale is RTL (right-to-left), <code>false</code> otherwise
+ */
+ public boolean isRtlLocale() {
+ return rtlLocale;
+ }
+
+ /**
* Sets the metadata for this session using the given key. If the metadata object is not of the
* correct type for the metadata key, an IllegalArgumentException will be thrown. For
* information on creating MetaDataKeys, see {@link MetaDataKey}.
diff --git a/wicket-core/src/test/java/org/apache/wicket/protocol/http/WebSessionTest.java b/wicket-core/src/test/java/org/apache/wicket/protocol/http/WebSessionTest.java
index 2eb05a7..164cda6 100644
--- a/wicket-core/src/test/java/org/apache/wicket/protocol/http/WebSessionTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/protocol/http/WebSessionTest.java
@@ -17,11 +17,14 @@
package org.apache.wicket.protocol.http;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.util.Locale;
+import java.util.stream.Stream;
import org.apache.wicket.Session;
import org.apache.wicket.WicketRuntimeException;
@@ -31,6 +34,8 @@ import org.apache.wicket.protocol.http.mock.MockHttpSession;
import org.apache.wicket.request.Url;
import org.apache.wicket.util.tester.WicketTester;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
/**
* @author Timo Rantalaiho
@@ -87,7 +92,7 @@ class WebSessionTest
Session session = tester.getSession();
session.getPageManager();
-
+
session.detach();
try
@@ -100,4 +105,52 @@ class WebSessionTest
assertEquals("The request has been processed. Access to pages is no longer allowed", ex.getMessage());
}
}
+
+ private static Stream<String> provideLTRtags() {
+ return Stream.of("en", "en-US", "ko", "bg", "ar-Latn", "fa-Cyrl");
+ }
+
+ private static Stream<String> provideRTLtags() {
+ return Stream.of("ar", "dv", "he", "iw", "fa", "nqo", "ps", "sd", "ug", "ur", "yi", "en-Arab-US", "ru-Hebr", "nl-Thaa", "fi-Nkoo", "fr-Tfng");
+ }
+
+ private Session createSessionViaConstructor(String langTag) {
+ MockWebRequest rq = new MockWebRequest(Url.parse("/"));
+ rq.setLocale(Locale.forLanguageTag(langTag));
+ return new WebSession(rq);
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideLTRtags")
+ void testConstructorLtr(String langTag) {
+ Session session = createSessionViaConstructor(langTag);
+ assertFalse(session.isRtlLocale(), langTag + " should be LTR (left-to-right)");
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideRTLtags")
+ void testConstructorRtl(String langTag) {
+ Session session = createSessionViaConstructor(langTag);
+ assertTrue(session.isRtlLocale(), langTag + " should be RTL (right-to-left)");
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideLTRtags")
+ void testSetterLtr(String langTag) {
+ WicketTester tester = new WicketTester(new MockApplication());
+ Session session = tester.getSession();
+
+ session.setLocale(Locale.forLanguageTag(langTag));
+ assertFalse(session.isRtlLocale(), langTag + " should be LTR (left-to-right)");
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideRTLtags")
+ void testSetterRtl(String langTag) {
+ WicketTester tester = new WicketTester(new MockApplication());
+ Session session = tester.getSession();
+
+ session.setLocale(Locale.forLanguageTag(langTag));
+ assertTrue(session.isRtlLocale(), langTag + " should be RTL (right-to-left)");
+ }
}