All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.mmm.base.i18n.LocaleHelper Maven / Gradle / Ivy

/* Copyright (c) The m-m-m Team, Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0 */
package io.github.mmm.base.i18n;

import java.util.Locale;
import java.util.Locale.Builder;

import io.github.mmm.base.filter.CharFilter;

/**
 * Simple helper for {@link Locale} specific stuff.
 *
 * @since 1.0.0
 */
public final class LocaleHelper {

  /** The default separator used for {@link #toInfixes(Locale) locale-infixes}. */
  public static final char SEPARATOR_DEFAULT = '_';

  /** The separator used for {@link Locale#forLanguageTag(String) language tag}. */
  public static final char SEPARATOR_FOR_LANGUAGE_TAG = '-';

  /** The separator used for {@link Locale#getExtensionKeys() extension keys}. */
  public static final char SEPARATOR_EXTENSION = '-';

  /** The separator used for {@link Locale#getScript() script}. */
  public static final char SEPARATOR_SCRIPT = '#';

  private LocaleHelper() {

    super();
  }

  /**
   * @param locale is the {@link Locale}.
   * @return the localization-infix in the form
   *         [_{@link Locale#getLanguage() language}[_{@link Locale#getCountry() country}[_{@link Locale#getVariant() variant}]]].
   *         Will be the empty {@link String} for the {@link Locale#ROOT root locale}. E.g. for {@link Locale#GERMANY}
   *         this method will return "_de_DE".
   */
  public static String toInfix(Locale locale) {

    StringBuilder infix = new StringBuilder();
    String language = locale.getLanguage();
    boolean hasLanguage = (language != null) && (language.length() == 2);
    if (hasLanguage) {
      infix.append(SEPARATOR_DEFAULT);
      infix.append(language);
    }
    String country = locale.getCountry();
    boolean hasCountry = (country != null) && (country.length() == 2);
    if (hasCountry) {
      if (!hasLanguage) {
        infix.append(SEPARATOR_DEFAULT);
      }
      infix.append(SEPARATOR_DEFAULT);
      infix.append(country);
    }
    String variant = locale.getVariant();
    if ((variant != null) && (variant.length() > 0)) {
      if (!hasCountry) {
        infix.append(SEPARATOR_DEFAULT);
        if (!hasLanguage) {
          infix.append(SEPARATOR_DEFAULT);
        }
      }
      infix.append(SEPARATOR_DEFAULT);
      infix.append(variant);
    }
    return infix.toString();
  }

  /**
   * This method determines the infix-strings for localization lookup ordered from most specific to least specific
   * (empty string representing {@link Locale#ROOT}). Each infix is defined as:
   *
   * 
   * [_{@link Locale#getLanguage() language}[_{@link Locale#getCountry() country}[_{@link Locale#getVariant() variant}]]]
   * 
* * Please note that if a segment is empty but a following segment is present, multiple underscores ('_') will occur. *
* Examples: * * * * * * * * * * * * * * * * * *
localeresult
{@link Locale#GERMANY}{"_de_DE", "_de", ""}
new {@link Locale#Locale(String, String) Locale}("", "CM"){"__CM", ""}
new {@link Locale#Locale(String, String, String) Locale}("", "", "variant"){"___variant", ""}
* * @param locale is the {@link Locale}. * @return the localization-infixes ordered from most specific to least specific. The returned array will always * contain the empty string as last entry. */ public static String[] toInfixes(Locale locale) { String[] infixes; int length = 1; StringBuilder infix = new StringBuilder(); String infixLang = null; String language = locale.getLanguage(); infix.append(SEPARATOR_DEFAULT); if ((language != null) && (language.length() == 2)) { infix.append(language); infixLang = infix.toString(); length++; } String infixCountry = null; String country = locale.getCountry(); infix.append(SEPARATOR_DEFAULT); if ((country != null) && (country.length() == 2)) { infix.append(country); infixCountry = infix.toString(); length++; } String infixVariant = null; String variant = locale.getVariant(); infix.append(SEPARATOR_DEFAULT); if ((variant != null) && (variant.length() > 0)) { infix.append(variant); infixVariant = infix.toString(); length++; } infixes = new String[length]; int i = 0; if (infixVariant != null) { infixes[i] = infixVariant; i++; } if (infixCountry != null) { infixes[i] = infixCountry; i++; } if (infixLang != null) { infixes[i] = infixLang; i++; } infixes[i] = ""; return infixes; } /** * Create a {@link Locale} from a given {@link String} representation such as {@link Locale#toString()} or * {@link Locale#forLanguageTag(String)}. * * @param locale the {@link String} representation of the {@link Locale}. May be an from {@link Locale#toString()}, * {@link Locale#toLanguageTag()} or {@link #toInfix(Locale)}. * @return the parsed {@link Locale}. */ public static Locale fromString(String locale) { if (locale == null) { return null; } if (locale.isEmpty()) { return Locale.ROOT; } int start = 0; int end = locale.indexOf(SEPARATOR_DEFAULT); if (end == -1) { if (locale.charAt(0) == SEPARATOR_FOR_LANGUAGE_TAG) { locale = locale.substring(1); // tolerant for accepting suffixes like "-en-US" } return Locale.forLanguageTag(locale); } else if (end == 0) { start = end + 1; end = locale.indexOf(SEPARATOR_DEFAULT, start); } Builder builder = new Builder(); if (end == -1) { builder.setLanguage(locale.substring(start)); } else { String language = locale.substring(start, end); builder.setLanguage(language); start = end + 1; end = locale.indexOf(SEPARATOR_DEFAULT, start); if (end == -1) { builder.setRegion(locale.substring(start)); } else { String region = locale.substring(start, end); builder.setRegion(region); String variant = fromStringDetails(locale, end + 1, builder); if (variant != null) { return new Locale(language, region, variant); } } } return builder.build(); } private static String fromStringDetails(String locale, int start, Builder builder) { int len = locale.length(); if (start >= len) { return null; } int end; char c = locale.charAt(start); if (c != SEPARATOR_SCRIPT) { // variant? end = locale.indexOf(SEPARATOR_DEFAULT, start); String variant; if (end == -1) { variant = locale.substring(start); } else { variant = locale.substring(start, end); start = end + 1; if (start < len) { c = locale.charAt(start); } } try { builder.setVariant(variant); } catch (Exception e) { return variant; } } if (c == SEPARATOR_SCRIPT) { // script/extension? start++; end = locale.indexOf(SEPARATOR_EXTENSION, start); if (end == -1) { builder.setScript(locale.substring(start)); } else if (end > start + 1) { builder.setScript(locale.substring(start, end)); start = end + 1; } end = findExtensionKey(locale, start); while (end != -1) { char extensionKey = locale.charAt(end); start = end + 2; end = findExtensionKey(locale, start); String value; if (end == -1) { value = locale.substring(start); } else { value = locale.substring(start, end - 1); } if (!value.isEmpty()) { builder.setExtension(extensionKey, value); } } } return null; } private static int findExtensionKey(String locale, int start) { while (true) { int end = locale.indexOf(SEPARATOR_EXTENSION, start); if (end == -1) { return -1; } if (end == start + 1) { char extensionKey = locale.charAt(start); if (CharFilter.LATIN_LETTER_OR_DIGIT.accept(extensionKey)) { return start; } } else { start = end + 1; } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy