/*******************************************************************************
* Copyright (c) 2015
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*******************************************************************************/
package jsettlers.graphics.localization;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Locale;
import java.util.Properties;
/**
* This is a class that helps with the locale management. Don't use it directly, use {@link Labels} instead.
*
* @author Michael Zangl
*
*/
public abstract class AbstractLabels {
private static Locale preferredLocale = Locale.getDefault();
/**
* This defines a locale suffix (like _en_US).
*
* @author Michael Zangl
*/
public static class LocaleSuffix {
private static final String SEPARATOR = "_";
private Locale locale;
private boolean useCountry;
/**
* Creates a new locale suffix object.
*
* @param locale
* The locale to use.
* @param useCountry
* The we should interpret the country field of the locale.
*/
public LocaleSuffix(Locale locale, boolean useCountry) {
this.locale = locale;
this.useCountry = useCountry;
}
/**
* Gets the locale used.
*
* @return The {@link Locale}
*/
public Locale getLocale() {
return locale;
}
/**
* Creates a file name with this suffix.
*
* @param prefix
* The file prefix.
* @param suffix
* The file ending to append after the name.
* @return The new name.
*/
public String getFileName(String prefix, String suffix) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(prefix);
stringBuilder.append(SEPARATOR);
stringBuilder.append(locale.getLanguage());
if (useCountry) {
stringBuilder.append(SEPARATOR);
stringBuilder.append(locale.getCountry());
}
stringBuilder.append(suffix);
return stringBuilder.toString();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("LocaleSuffix [locale=");
builder.append(locale);
builder.append(", useCountry=");
builder.append(useCountry);
builder.append("]");
return builder.toString();
}
}
private Properties loadedLabels;
private boolean labelsLoaded;
/**
* The most dominant locale that was used.
*/
private Locale usedLocale;
private synchronized Properties getLabels() {
if (!labelsLoaded) {
loadLabels();
labelsLoaded = true;
}
return loadedLabels;
}
private void loadLabels() {
LocaleSuffix[] locales = getLocaleSuffixes();
for (LocaleSuffix locale : locales) {
try {
Properties currentLocaleLabels = new Properties(loadedLabels);
InputStream inputStream = getLocaleStream(locale);
if (inputStream == null) {
throw new IOException();
}
currentLocaleLabels.load(new InputStreamReader(inputStream, "UTF-8"));
loadedLabels = currentLocaleLabels;
// Store the most dominant locale found.
usedLocale = locale.getLocale();
} catch (IOException e) {
System.err.println("Warning: Could not load " + locale + ". Falling back to next file.");
}
}
}
/**
* Generates an input stream for the given locale.
*
* @param locale
* The locale to generate the input stream for.
* @return The stream.
* @throws IOException
* If the stream could not be generated.
*/
protected abstract InputStream getLocaleStream(LocaleSuffix locale) throws IOException;
/**
* Gets a list of locale suffixes.
*
* @return The list, ordered from least to most preferred.
*/
public LocaleSuffix[] getLocaleSuffixes() {
LocaleSuffix[] locales = new LocaleSuffix[] {
new LocaleSuffix(new Locale("en"), false),
new LocaleSuffix(preferredLocale, false),
new LocaleSuffix(preferredLocale, true),
};
return locales;
}
/**
* Gets a string.
*
* @param key
* The name of the string
* @return The localized string
*/
public String getSingleString(String key) {
Properties labels = getLabels();
if (labels != null) {
String value = labels.getProperty(key);
if (value != null) {
return value;
}
}
return key;
}
/**
* Gets the locale that was used.
*
* @return The locale.
*/
public Locale getUsedLocale() {
return usedLocale;
}
/**
* Sets the preferred locale to use. This is only regarded when creating new locale objects.
*
* @param preferredLocale
* The new proffered locale.
*/
public static void setPreferredLocale(Locale preferredLocale) {
AbstractLabels.preferredLocale = preferredLocale;
}
}