Merge pull request #351 from chenejac/supportingPrivateTags

[3800 i18n redesign] Supporting private tags
This commit is contained in:
Georgy Litvinov 2022-12-13 16:50:02 +01:00 committed by GitHub
commit f548908b32
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 58 additions and 24 deletions

View file

@ -170,7 +170,7 @@ public class ViewLabelsServlet extends FreemarkerHttpServlet{
Locale currentLocale) throws FileNotFoundException { Locale currentLocale) throws FileNotFoundException {
HashMap<String, String> map = new HashMap<String, String>(); HashMap<String, String> map = new HashMap<String, String>();
//Replacing the underscore with a hyphen because that is what is represented in the actual literals //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)); map.put("label", locale.getDisplayName(currentLocale));
return map; return map;
} }

View file

@ -464,7 +464,7 @@ public class ManageLabelsForIndividualGenerator extends BaseEditConfigurationGen
Locale currentLocale) throws FileNotFoundException { Locale currentLocale) throws FileNotFoundException {
HashMap<String, String> map = new HashMap<String, String>(); HashMap<String, String> map = new HashMap<String, String>();
//Replacing the underscore with a hyphen because that is what is represented in the actual literals //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)); map.put("label", locale.getDisplayName(currentLocale));
return map; return map;
} }

View file

@ -284,7 +284,7 @@ public class CachingResponseFilter implements Filter {
StringBuilder buffer = new StringBuilder("\"").append(rawEtag); StringBuilder buffer = new StringBuilder("\"").append(rawEtag);
for (Locale locale : locales) { for (Locale locale : locales) {
buffer.append(locale.toString()); buffer.append(locale.toLanguageTag());
} }
buffer.append("\""); buffer.append("\"");

View file

@ -88,7 +88,7 @@ public class LocaleSelectionController extends HttpServlet {
if (!selectables.contains(locale)) { if (!selectables.contains(locale)) {
log.warn("User selected a locale '" + locale log.warn("User selected a locale '" + locale
+ "' that was not in the list: " + selectables); + "' 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 + "'"); log.warn("User selected an unrecognized locale: '" + locale + "'");
} }

View file

@ -3,12 +3,7 @@
package edu.cornell.mannlib.vitro.webapp.i18n.selection; package edu.cornell.mannlib.vitro.webapp.i18n.selection;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -36,7 +31,8 @@ import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetter;
* { [a map for each Locale] * { [a map for each Locale]
* code = [the code for the Locale, e.g. "en_US"] * code = [the code for the Locale, e.g. "en_US"]
* label = [the alt text for the Locale, e.g. "Spanish (Spain)"] * 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] * selected = [true, if this locale is currently selected]
* } * }
* } * }
@ -50,6 +46,8 @@ public class LocaleSelectionDataGetter implements DataGetter {
private final VitroRequest vreq; private final VitroRequest vreq;
private static final char PRIVATE_USE_SUBTAG = 'x';
public LocaleSelectionDataGetter(VitroRequest vreq) { public LocaleSelectionDataGetter(VitroRequest vreq) {
this.vreq = vreq; this.vreq = vreq;
} }
@ -73,10 +71,23 @@ public class LocaleSelectionDataGetter implements DataGetter {
private List<Map<String, Object>> buildLocalesList(List<Locale> selectables) { private List<Map<String, Object>> buildLocalesList(List<Locale> selectables) {
Locale currentLocale = SelectedLocale.getCurrentLocale(vreq); 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<String> setOfLocalesBase = new HashSet<>();
for(final Locale locale: selectables) {
setOfLocalesBase.add(locale.stripExtensions().toLanguageTag());
}
if (setOfLocalesBase.size() < selectables.size()) {
includeAbbreviation = true;
}
List<Map<String, Object>> list = new ArrayList<>(); List<Map<String, Object>> list = new ArrayList<>();
for (Locale locale : selectables) { for (Locale locale : selectables) {
try { try {
list.add(buildLocaleMap(locale, currentLocale)); list.add(buildLocaleMap(locale, currentLocale, includeAbbreviation));
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
log.warn("Can't show the Locale selector for '" + locale log.warn("Can't show the Locale selector for '" + locale
+ "': " + e); + "': " + e);
@ -86,12 +97,15 @@ public class LocaleSelectionDataGetter implements DataGetter {
} }
private Map<String, Object> buildLocaleMap(Locale locale, private Map<String, Object> buildLocaleMap(Locale locale,
Locale currentLocale) throws FileNotFoundException { Locale currentLocale, boolean includeAbbreviation) throws FileNotFoundException {
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put("code", locale.toLanguageTag().replace('-','_')); map.put("code", locale.toLanguageTag().replace('-','_'));
map.put("label", locale.getDisplayLanguage(locale)); map.put("label", locale.getDisplayLanguage(locale));
map.put("country", locale.getDisplayCountry(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)); map.put("selected", currentLocale.equals(locale));
return map; return map;
} }

View file

@ -154,7 +154,7 @@ public class LocaleSelectionSetup implements ServletContextListener {
Locale locale = LocaleUtility.languageStringToLocale(localeString); Locale locale = LocaleUtility.languageStringToLocale(localeString);
if (!"es_GO".equals(localeString) && // No complaint about bogus locale if (!"es_GO".equals(localeString) && // No complaint about bogus locale
!LocaleUtils.isAvailableLocale(locale)) { !LocaleUtils.isAvailableLocale(locale.stripExtensions())) {
ssWarning("'" + locale + "' is not a recognized locale."); ssWarning("'" + locale + "' is not a recognized locale.");
} }

View file

@ -33,7 +33,7 @@ public class LanguageFilteringUtils {
* (as in RDF language specifiers). * (as in RDF language specifiers).
*/ */
public static String localeToLanguage(Locale locale) { 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<String> langs = new ArrayList<>(); List<String> langs = new ArrayList<>();
while (locales.hasMoreElements()) { while (locales.hasMoreElements()) {
Locale locale = (Locale) locales.nextElement(); 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)) { if (!langs.contains(DEFAULT_LANG_STRING)) {
langs.add(DEFAULT_LANG_STRING); langs.add(DEFAULT_LANG_STRING);

View file

@ -136,7 +136,19 @@ public class RDFFilesLoader {
// Which locales are enabled in runtime.properties? // Which locales are enabled in runtime.properties?
List<Locale> locales = SelectedLocale.getSelectableLocales(ctx); List<Locale> locales = SelectedLocale.getSelectableLocales(ctx);
for (Locale locale : locales) { 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 // If no languages were enabled in runtime.properties, add a fallback as the default

View file

@ -10,10 +10,17 @@ public final class LocaleUtility {
public static Locale languageStringToLocale(String localeString){ public static Locale languageStringToLocale(String localeString){
String[] parsedLoc = localeString.trim().split("_", -1); String[] parsedLoc = localeString.trim().split("_", -1);
//regex pattern for locale tag with script specified Locale locale = null;
Locale locale = localeString.matches("^[a-z]{1,3}_[A-Z][a-z]{3}_[A-Z]{2}") ? if (localeString.matches("^[a-z]{1,3}_[A-Z][a-z]{3}_[A-Z]{2}_x_[a-z]{1,}")) { //regex pattern for locale tag with script and private-use subtag, e.g. sr_Latn_RS_x_uns
new Locale.Builder().setLanguage(parsedLoc[0]).setRegion(parsedLoc[2]).setScript(parsedLoc[1]).build() : locale = new Locale.Builder().setLanguage(parsedLoc[0]).setRegion(parsedLoc[2]).setScript(parsedLoc[1]).setExtension('x', parsedLoc[4]).build();
LocaleUtils.toLocale(localeString); } else if (localeString.matches("^[a-z]{1,3}_[A-Za-z]{2}_x_[a-z]{1,}")) { //regex pattern for locale tag with script and private-use subtag, e.g. fr_CA_x_uqam
locale = new Locale.Builder().setLanguage(parsedLoc[0]).setRegion(parsedLoc[1]).setExtension('x', parsedLoc[3]).build();
} else if (localeString.matches("^[a-z]{1,3}_[A-Z][a-z]{3}_[A-Z]{2}")) { //regex pattern for locale tag with script specified, e.g. sr_Latn_RS
locale = new Locale.Builder().setLanguage(parsedLoc[0]).setRegion(parsedLoc[2]).setScript(parsedLoc[1]).build();
} else { // other, just languge, e.g. es, or language + region, e.g. en_US, pt_BR, ru_RU, etc.
locale = LocaleUtils.toLocale(localeString);
}
String localeLang = locale.toLanguageTag();
return locale; return locale;
} }
} }

View file

@ -209,11 +209,11 @@ public class SearchQueryUtils {
} }
public static String getSortFieldNameForLocale(Locale locale) { 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) { 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<String> vclassUris, int page, int pageSize){ public static SearchQuery getRandomQuery(List<String> vclassUris, int page, int pageSize){

View file

@ -6,7 +6,7 @@
<#list selectLocale.locales as locale> <#list selectLocale.locales as locale>
<li <#if locale.selected>status="selected"</#if>> <li <#if locale.selected>status="selected"</#if>>
<a href="${selectLocale.selectLocaleUrl}?selection=${locale.code}" title="${i18n().select_locale} -- ${locale.label}">${locale.label?capitalize}<#if locale.country?has_content> (${locale.country})</#if></a> <a href="${selectLocale.selectLocaleUrl}?selection=${locale.code}" title="${i18n().select_locale} -- ${locale.label}">${locale.label?capitalize}<#if locale.country?has_content> (${locale.country})</#if><#if locale.institution?has_content> - ${locale.institution}</#if></a>
</li> </li>
</#list> </#list>
</ul> </ul>
@ -21,6 +21,7 @@
* -- code * -- code
* -- label (tooltip displayed in original locale, not current locale) * -- label (tooltip displayed in original locale, not current locale)
* -- country (displayed in original locale, not current locale) * -- country (displayed in original locale, not current locale)
* -- institution (abbreviation)
* -- selected (boolean) * -- selected (boolean)
--> -->
<script type="text/javascript"> <script type="text/javascript">