/* * Copyright 2015 MovingBlocks * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.terasology.i18n; import com.google.common.collect.ImmutableMap; import javax.annotation.concurrent.Immutable; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.Objects; /** * I18nMap is a map of Strings by Locale, to support lookup fields that can have different values for different languages (internationalized fields). * <p> * This is not intended to be used as a replacement of Java's existing internationalisation support for strings, but instead used for * internationalised strings read from external sources. * </p> * <p> * If a String is not available for a particular locale, then it will fallback though the following steps to find one: * </p> * <ol> * <li>Drop Locale variant</li> * <li>Drop Locale country</li> * <li>Use system default display Locale</li> * <li>Use English Locale</li> * <li>Use any available Locale</li> * </ol> * * @author Immortius */ @Immutable public class I18nMap implements Iterable<Map.Entry<Locale, String>> { private final Map<Locale, String> values; /** * Constructor when a mapping of Locale to String is available. * * @param values A map of locale-string values. */ public I18nMap(Map<Locale, String> values) { this.values = ImmutableMap.copyOf(values); } /** * Constructor when only a single String is available - this will be registered against the default Locale. * * @param value The sole value of this map. */ public I18nMap(String value) { values = ImmutableMap.of(Locale.getDefault(Locale.Category.DISPLAY), value); } /** * @return The most appropriate string value to use based on the system default Locale */ public String value() { String result = values.get(Locale.getDefault(Locale.Category.DISPLAY)); if (result == null) { result = values.get(Locale.ENGLISH); } if (result == null && !values.isEmpty()) { result = values.values().iterator().next(); } if (result == null) { result = ""; } return result; } /** * @param locale The locale to get the string value for * @return The most appropriate string value for the given locale. */ public String valueFor(Locale locale) { String result = values.get(locale); if (result == null && !locale.getVariant().isEmpty()) { Locale fallbackLocale = new Locale(locale.getLanguage(), locale.getCountry()); result = values.get(fallbackLocale); } if (result == null && !locale.getCountry().isEmpty()) { Locale fallbackLocale = new Locale(locale.getLanguage()); result = values.get(fallbackLocale); } if (result == null) { result = value(); } return result; } /** * @return The most appropriate string value based on the system default locale. */ @Override public String toString() { return value(); } @Override public Iterator<Map.Entry<Locale, String>> iterator() { return values.entrySet().iterator(); } @Override public int hashCode() { return Objects.hash(values); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof I18nMap) { I18nMap other = (I18nMap) obj; return Objects.equals(values, other.values); } return false; } }