From 62cbcca8dc08c1f4d0303cb168ca70ec9e97aac7 Mon Sep 17 00:00:00 2001 From: Dragan Ivanovic Date: Tue, 29 Nov 2022 13:24:04 +0100 Subject: [PATCH 1/3] support for private subtag (x) --- .../i18n/selection/LocaleSelectionSetup.java | 2 +- .../vitro/webapp/utils/LocaleUtility.java | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetup.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetup.java index 98ff8b02f..2884cfaa9 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetup.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionSetup.java @@ -154,7 +154,7 @@ public class LocaleSelectionSetup implements ServletContextListener { Locale locale = LocaleUtility.languageStringToLocale(localeString); if (!"es_GO".equals(localeString) && // No complaint about bogus locale - !LocaleUtils.isAvailableLocale(locale)) { + !LocaleUtils.isAvailableLocale(locale.stripExtensions())) { ssWarning("'" + locale + "' is not a recognized locale."); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/LocaleUtility.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/LocaleUtility.java index efbe51288..4c6bf5745 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/LocaleUtility.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/LocaleUtility.java @@ -10,10 +10,20 @@ public final class LocaleUtility { public static Locale languageStringToLocale(String localeString){ String[] parsedLoc = localeString.trim().split("_", -1); - //regex pattern for locale tag with script specified - Locale locale = localeString.matches("^[a-z]{1,3}_[A-Z][a-z]{3}_[A-Z]{2}") ? - new Locale.Builder().setLanguage(parsedLoc[0]).setRegion(parsedLoc[2]).setScript(parsedLoc[1]).build() : - LocaleUtils.toLocale(localeString); + Locale locale = null; + //regex pattern for locale tag with script and private-use subtag, e.g. sr_Latn_RS_x_uns + if (localeString.matches("^[a-z]{1,3}_[A-Z][a-z]{3}_[A-Z]{2}_x_[a-z]{1,}")) + locale = new Locale.Builder().setLanguage(parsedLoc[0]).setRegion(parsedLoc[2]).setScript(parsedLoc[1]).setExtension('x', parsedLoc[4]).build(); + //regex pattern for locale tag with script and private-use subtag, e.g. fr_CA_x_uqam + if (localeString.matches("^[a-z]{1,3}_[A-Za-z]{2}_x_[a-z]{1,}")) + locale = new Locale.Builder().setLanguage(parsedLoc[0]).setRegion(parsedLoc[1]).setExtension('x', parsedLoc[3]).build(); + //regex pattern for locale tag with script specified, e.g. sr_Latn_RS + else if (localeString.matches("^[a-z]{1,3}_[A-Z][a-z]{3}_[A-Z]{2}")) + locale = new Locale.Builder().setLanguage(parsedLoc[0]).setRegion(parsedLoc[2]).setScript(parsedLoc[1]).build(); + // other, just languge, e.g. es, or language + region, e.g. en_US, pt_BR, ru_RU, etc. + else + locale = LocaleUtils.toLocale(localeString); + String localeLang = locale.toLanguageTag(); return locale; } } From 6312b966f2e172dbe0c5add510bbd929fe0d4482 Mon Sep 17 00:00:00 2001 From: Dragan Ivanovic Date: Thu, 8 Dec 2022 14:20:52 +0100 Subject: [PATCH 2/3] adding support for private subtags in the language tags, replacement of toString() method with toLanguageTag() method, adding checks for locale.stripExtensions() where it was neccessary, adding information about private tag in the drop down selection of a UI language --- .../freemarker/ViewLabelsServlet.java | 2 +- .../ManageLabelsForIndividualGenerator.java | 2 +- .../webapp/filters/CachingResponseFilter.java | 2 +- .../selection/LocaleSelectionController.java | 2 +- .../selection/LocaleSelectionDataGetter.java | 30 +++++++++++++------ .../filter/LanguageFilteringUtils.java | 4 +-- .../webapp/servlet/setup/RDFFilesLoader.java | 12 +++++++- .../utils/searchengine/SearchQueryUtils.java | 4 +-- .../page/partials/languageSelector.ftl | 3 +- 9 files changed, 42 insertions(+), 19 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ViewLabelsServlet.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ViewLabelsServlet.java index f68db8d56..69286eb50 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ViewLabelsServlet.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ViewLabelsServlet.java @@ -170,7 +170,7 @@ public class ViewLabelsServlet extends FreemarkerHttpServlet{ Locale currentLocale) throws FileNotFoundException { HashMap map = new HashMap(); //Replacing the underscore with a hyphen because that is what is represented in the actual literals - map.put("code", locale.toString().replace("_", "-")); + map.put("code", locale.toLanguageTag().replace("_", "-")); map.put("label", locale.getDisplayName(currentLocale)); return map; } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForIndividualGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForIndividualGenerator.java index 3f7e912bb..3e03abcf7 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForIndividualGenerator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManageLabelsForIndividualGenerator.java @@ -464,7 +464,7 @@ public class ManageLabelsForIndividualGenerator extends BaseEditConfigurationGen Locale currentLocale) throws FileNotFoundException { HashMap map = new HashMap(); //Replacing the underscore with a hyphen because that is what is represented in the actual literals - map.put("code", locale.toString().replace("_", "-")); + map.put("code", locale.toLanguageTag().replace("_", "-")); map.put("label", locale.getDisplayName(currentLocale)); return map; } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/CachingResponseFilter.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/CachingResponseFilter.java index 93c86ad9d..ea88a0d28 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/CachingResponseFilter.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/filters/CachingResponseFilter.java @@ -284,7 +284,7 @@ public class CachingResponseFilter implements Filter { StringBuilder buffer = new StringBuilder("\"").append(rawEtag); for (Locale locale : locales) { - buffer.append(locale.toString()); + buffer.append(locale.toLanguageTag()); } buffer.append("\""); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionController.java index aa013c965..ba47e443f 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionController.java @@ -88,7 +88,7 @@ public class LocaleSelectionController extends HttpServlet { if (!selectables.contains(locale)) { log.warn("User selected a locale '" + locale + "' that was not in the list: " + selectables); - } else if (!LocaleUtils.isAvailableLocale(locale)) { + } else if (!LocaleUtils.isAvailableLocale(locale.stripExtensions())) { log.warn("User selected an unrecognized locale: '" + locale + "'"); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionDataGetter.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionDataGetter.java index 17fa89fed..3fca0efed 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionDataGetter.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/i18n/selection/LocaleSelectionDataGetter.java @@ -3,12 +3,7 @@ package edu.cornell.mannlib.vitro.webapp.i18n.selection; import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.util.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -36,7 +31,8 @@ import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetter; * { [a map for each Locale] * code = [the code for the Locale, e.g. "en_US"] * label = [the alt text for the Locale, e.g. "Spanish (Spain)"] - * imageUrl = [the URL of the image that represents the Locale] + * country = [the country for the Locale, e.g. "United States"] + * institution = [the abbreviation for institution, e.g. "UQAM"] * selected = [true, if this locale is currently selected] * } * } @@ -50,6 +46,8 @@ public class LocaleSelectionDataGetter implements DataGetter { private final VitroRequest vreq; + private static final char PRIVATE_USE_SUBTAG = 'x'; + public LocaleSelectionDataGetter(VitroRequest vreq) { this.vreq = vreq; } @@ -73,10 +71,22 @@ public class LocaleSelectionDataGetter implements DataGetter { private List> buildLocalesList(List selectables) { Locale currentLocale = SelectedLocale.getCurrentLocale(vreq); + // The next couple of lines check whether there are locales in the list with the same root. + // If yes, the institution abbreviation (private tag) will be displayed in UI. + // For instance, if there are fr_CA_x_uqam and fr_CA in a VIVO instance runtime.properties, + // the institutional abbreviation (UQAM) will be displayed next to locale name + // in the dropdown menu for selection of a UI language. + boolean includeAbbreviation = false; + Set setOfLocalesBase = new HashSet<>(); + for(final Locale locale: selectables) { + setOfLocalesBase.add(locale.stripExtensions().toLanguageTag()); + } + if (setOfLocalesBase.size() < selectables.size()) + includeAbbreviation = true; List> list = new ArrayList<>(); for (Locale locale : selectables) { try { - list.add(buildLocaleMap(locale, currentLocale)); + list.add(buildLocaleMap(locale, currentLocale, includeAbbreviation)); } catch (FileNotFoundException e) { log.warn("Can't show the Locale selector for '" + locale + "': " + e); @@ -86,12 +96,14 @@ public class LocaleSelectionDataGetter implements DataGetter { } private Map buildLocaleMap(Locale locale, - Locale currentLocale) throws FileNotFoundException { + Locale currentLocale, boolean includeAbbreviation) throws FileNotFoundException { Map map = new HashMap<>(); map.put("code", locale.toLanguageTag().replace('-','_')); map.put("label", locale.getDisplayLanguage(locale)); map.put("country", locale.getDisplayCountry(locale)); + if (includeAbbreviation) + map.put("institution", Optional.ofNullable(locale.getExtension(LocaleSelectionDataGetter.PRIVATE_USE_SUBTAG)).orElse("").toUpperCase()); map.put("selected", currentLocale.equals(locale)); return map; } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringUtils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringUtils.java index c7f5fcfe0..7be5b7816 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringUtils.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringUtils.java @@ -33,7 +33,7 @@ public class LanguageFilteringUtils { * (as in RDF language specifiers). */ public static String localeToLanguage(Locale locale) { - return locale.toString().replace(UNDERSCORE, HYPHEN); + return locale.toLanguageTag().replace(UNDERSCORE, HYPHEN); } /** @@ -69,7 +69,7 @@ public class LanguageFilteringUtils { List langs = new ArrayList<>(); while (locales.hasMoreElements()) { Locale locale = (Locale) locales.nextElement(); - langs.add(locale.toString().replace(UNDERSCORE, HYPHEN)); + langs.add(locale.toLanguageTag().replace(UNDERSCORE, HYPHEN)); } if (!langs.contains(DEFAULT_LANG_STRING)) { langs.add(DEFAULT_LANG_STRING); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/servlet/setup/RDFFilesLoader.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/servlet/setup/RDFFilesLoader.java index c8535c76f..3ad5f4f31 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/servlet/setup/RDFFilesLoader.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/servlet/setup/RDFFilesLoader.java @@ -136,7 +136,17 @@ public class RDFFilesLoader { // Which locales are enabled in runtime.properties? List locales = SelectedLocale.getSelectableLocales(ctx); for (Locale locale : locales) { - enabledLocales.add(locale.toLanguageTag().replace('-', '_')); + String localeString = locale.toLanguageTag().replace('-', '_'); + if (! enabledLocales.contains(localeString)) + enabledLocales.add(localeString); + // If a locale with fr_CA_x_uqam is used, the locale fr_CA should be also enabled for loading. + // Private tags (lang_CountryCode_x_InstitutionAbbreviation) are inteded to be just extension, + // therefore the basic locale (lang_CountryCode) should be loaded as well. + if(locale.hasExtensions()){ + localeString = locale.stripExtensions().toLanguageTag().replace('-', '_'); + if (! enabledLocales.contains(localeString)) + enabledLocales.add(localeString); + } } // If no languages were enabled in runtime.properties, add a fallback as the default diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/searchengine/SearchQueryUtils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/searchengine/SearchQueryUtils.java index ae99b6044..d1c5c471d 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/searchengine/SearchQueryUtils.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/searchengine/SearchQueryUtils.java @@ -209,11 +209,11 @@ public class SearchQueryUtils { } public static String getSortFieldNameForLocale(Locale locale) { - return locale.toString().replace('_', '-') + VitroSearchTermNames.LABEL_SORT_SUFFIX; + return locale.toLanguageTag().replace('_', '-') + VitroSearchTermNames.LABEL_SORT_SUFFIX; } public static String getLabelFieldNameForLocale(Locale locale) { - return locale.toString().replace('_', '-') + VitroSearchTermNames.LABEL_DISPLAY_SUFFIX; + return locale.toLanguageTag().replace('_', '-') + VitroSearchTermNames.LABEL_DISPLAY_SUFFIX; } public static SearchQuery getRandomQuery(List vclassUris, int page, int pageSize){ diff --git a/webapp/src/main/webapp/templates/freemarker/page/partials/languageSelector.ftl b/webapp/src/main/webapp/templates/freemarker/page/partials/languageSelector.ftl index 9bb4b9047..794f2e34f 100644 --- a/webapp/src/main/webapp/templates/freemarker/page/partials/languageSelector.ftl +++ b/webapp/src/main/webapp/templates/freemarker/page/partials/languageSelector.ftl @@ -6,7 +6,7 @@ <#list selectLocale.locales as locale>
  • status="selected"> - ${locale.label?capitalize}<#if locale.country?has_content> (${locale.country}) + ${locale.label?capitalize}<#if locale.country?has_content> (${locale.country})<#if locale.institution?has_content> - ${locale.institution}
  • @@ -21,6 +21,7 @@ * -- code * -- label (tooltip displayed in original locale, not current locale) * -- country (displayed in original locale, not current locale) + * -- institution (abbreviation) * -- selected (boolean) -->