// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.tools; import java.util.Collection; import java.util.LinkedList; import java.util.Locale; public final class LanguageInfo { private LanguageInfo() { // Hide default constructor for utils classes } /** * Type of the locale to use * @since 5915 */ public enum LocaleType { /** The current default language */ DEFAULT, /** The current default language, but not english */ DEFAULTNOTENGLISH, /** The base language (i.e. pt for pt_BR) */ BASELANGUAGE, /** The standard english texts */ ENGLISH } /** * Replies the wiki language prefix for the given locale. The wiki language * prefix has the form 'Xy:' where 'Xy' is a ISO 639 language code in title * case (or Xy_AB: for sub languages). * * @param type the type * @return the wiki language prefix or {@code null} for {@link LocaleType#BASELANGUAGE}, when * base language is identical to default or english * @since 5915 */ public static String getWikiLanguagePrefix(LocaleType type) { if (type == LocaleType.ENGLISH) return ""; String code = getJOSMLocaleCode(); if (type == LocaleType.BASELANGUAGE) { if (code.matches("[^_]+_[^_]+")) { code = code.substring(0, 2); if ("en".equals(code)) return null; } else { return null; } } else if (type == LocaleType.DEFAULTNOTENGLISH && "en".equals(code)) { return null; } else if (code.matches(".+@.+")) { return code.substring(0, 1).toUpperCase(Locale.ENGLISH) + code.substring(1, 2) + '-' + code.substring(3, 4).toUpperCase(Locale.ENGLISH) + code.substring(4) + ':'; } return code.substring(0, 1).toUpperCase(Locale.ENGLISH) + code.substring(1) + ':'; } /** * Replies the wiki language prefix for the current locale. * * @return the wiki language prefix * @see Locale#getDefault() * @see #getWikiLanguagePrefix(LocaleType) */ public static String getWikiLanguagePrefix() { return getWikiLanguagePrefix(LocaleType.DEFAULT); } /** * Replies the JOSM locale code for the default locale. * * @return the JOSM locale code for the default locale * @see #getJOSMLocaleCode(Locale) */ public static String getJOSMLocaleCode() { return getJOSMLocaleCode(Locale.getDefault()); } /** * Replies the locale code used by JOSM for a given locale. * * In most cases JOSM uses the 2-character ISO 639 language code ({@link Locale#getLanguage()} * to identify the locale of a localized resource, but in some cases it may use the * programmatic name for locales, as replied by {@link Locale#toString()}. * * For unknown country codes and variants this function already does fallback to * internally known translations. * * @param locale the locale. Replies "en" if null. * @return the JOSM code for the given locale */ public static String getJOSMLocaleCode(Locale locale) { if (locale == null) return "en"; for (String full : getLanguageCodes(locale)) { if ("iw_IL".equals(full)) return "he"; else if ("in".equals(full)) return "id"; else if (I18n.hasCode(full)) // catch all non-single codes return full; } // return single code as fallback return locale.getLanguage(); } /** * Replies the locale code used by Java for a given locale. * * In most cases JOSM and Java uses the same codes, but for some exceptions this is needed. * * @param localeName the locale. Replies "en" if null. * @return the Java code for the given locale * @since 8232 */ public static String getJavaLocaleCode(String localeName) { if (localeName == null) return "en"; if ("ca@valencia".equals(localeName)) { localeName = "ca__valencia"; } else if ("he".equals(localeName)) { localeName = "iw_IL"; } else if ("id".equals(localeName)) { localeName = "in"; } return localeName; } /** * Replies the display string used by JOSM for a given locale. * * In most cases returns text replied by {@link Locale#getDisplayName()}, for some * locales an override is used (i.e. when unsupported by Java). * * @param locale the locale. Replies "en" if null. * @return the display string for the given locale * @since 8232 */ public static String getDisplayName(Locale locale) { return locale.getDisplayName(); } /** * Replies the locale used by Java for a given language code. * * Accepts JOSM and Java codes as input. * * @param localeName the locale code. * @return the resulting locale */ public static Locale getLocale(String localeName) { int country = localeName.indexOf('_'); int variant = localeName.indexOf('@'); if (variant < 0 && country >= 0) variant = localeName.indexOf('_', country+1); Locale l; if (variant > 0 && country > 0) { l = new Locale(localeName.substring(0, country), localeName.substring(country+1, variant), localeName.substring(variant + 1)); } else if (variant > 0) { l = new Locale(localeName.substring(0, variant), "", localeName.substring(variant + 1)); } else if (country > 0) { l = new Locale(localeName.substring(0, country), localeName.substring(country + 1)); } else { l = new Locale(localeName); } return l; } /** * Check if a new language is better than a previous existing. Can be used in classes where * multiple user supplied language marked strings appear and the best one is searched. Following * priorities: current language, english, any other * * @param oldLanguage the language code of the existing string * @param newLanguage the language code of the new string * @return true if new one is better * @since 8091 */ public static boolean isBetterLanguage(String oldLanguage, String newLanguage) { if (oldLanguage == null) return true; String want = getJOSMLocaleCode(); return want.equals(newLanguage) || (!want.equals(oldLanguage) && newLanguage.startsWith("en")); } /** * Replies the language prefix for use in XML elements (with a dot appended). * * @return the XML language prefix * @see #getJOSMLocaleCode() */ public static String getLanguageCodeXML() { String code = getJOSMLocaleCode(); code = code.replace('@', '-'); return code+'.'; } /** * Replies the language prefix for use in manifests (with an underscore appended). * * @return the manifest language prefix * @see #getJOSMLocaleCode() */ public static String getLanguageCodeManifest() { String code = getJOSMLocaleCode(); code = code.replace('@', '-'); return code+'_'; } /** * Replies a list of language codes for local names. Prefixes range from very specific * to more generic. * <ul> * <li>lang_COUNTRY@variant of the current locale</li> * <li>lang@variant of the current locale</li> * <li>lang_COUNTRY of the current locale</li> * <li>lang of the current locale</li> * </ul> * * @param l the locale to use, <code>null</code> for default locale * @return list of codes * @since 8283 */ public static Collection<String> getLanguageCodes(Locale l) { Collection<String> list = new LinkedList<>(); if (l == null) l = Locale.getDefault(); String lang = l.getLanguage(); String c = l.getCountry(); String v = l.getVariant(); if (c.isEmpty()) c = null; if (v != null && !v.isEmpty()) { if (c != null) list.add(lang+'_'+c+'@'+v); list.add(lang+'@'+v); } if (c != null) list.add(lang+'_'+c); list.add(lang); return list; } }