/*
*
* Copyright 2014 http://Bither.net
*
* 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 net.bither.languages;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import net.bither.utils.LocaliserUtils;
import java.awt.*;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Locale;
import java.util.ResourceBundle;
/**
* <p>Utility to provide the following to Views:</p>
* <ul>
* <li>Access to internationalised text strings</li>
* </ul>
*
* @since 0.0.1
*/
public class Languages {
public static final String BASE_NAME = "viewer";
/**
* Utilities have private constructors
*/
private Languages() {
}
/**
* <p>Provide an array of the available amount separators. A hard space '\u00a0' is needed to
* ensure that values do not wrap.</p>
*
* @return The array
*/
public static String[] getCurrencySeparators(boolean forGrouping) {
if (forGrouping) {
// Groups can be separated by comma, point and space
return new String[]{
Languages.safeText(MessageKey.DECIMAL_COMMA),
Languages.safeText(MessageKey.DECIMAL_POINT),
Languages.safeText(MessageKey.DECIMAL_SPACE)
};
} else {
// Decimals can be separated by comma and point only
return new String[]{
Languages.safeText(MessageKey.DECIMAL_COMMA),
Languages.safeText(MessageKey.DECIMAL_POINT)
};
}
}
/**
* @return Current locale from configuration
*/
public static Locale currentLocale() {
return LocaliserUtils.getLocale();
}
/**
* @param value The encoding of the locale (e.g. "ll", "ll_rr", "ll_rr_vv")
* @return A new resource bundle based on the locale
*/
public static Locale newLocaleFromCode(String value) {
Preconditions.checkNotNull(value, "'value' must be present");
String[] parameters = value.split("_");
Preconditions.checkState(parameters.length > 0, "'value' must not be empty");
final Locale newLocale;
switch (parameters.length) {
case 1:
newLocale = new Locale(parameters[0]);
break;
case 2:
newLocale = new Locale(parameters[0], parameters[1]);
break;
case 3:
newLocale = new Locale(parameters[0], parameters[1], parameters[2]);
break;
default:
throw new IllegalArgumentException("Unknown locale descriptor: " + value);
}
return newLocale;
}
/**
* @param key The key (treated as a direct format string if not present)
* @param values An optional collection of value substitutions for {@link java.text.MessageFormat}
* @return The localised text with any substitutions made
*/
public static String safeText(MessageKey key, Object... values) {
// Simplifies processing of empty text
if (key == null) {
return "";
}
ResourceBundle rb = currentResourceBundle();
final String message;
if (!rb.containsKey(key.getKey())) {
// If no key is present then use it direct
message = key.getKey();
} else {
// Must have the key to be here
message = rb.getString(key.getKey());
}
return MessageFormat.format(message, values);
}
/**
* @param key The key (must be present in the bundle)
* @param values An optional collection of value substitutions for {@link java.text.MessageFormat}
* @return The localised text with any substitutions made
*/
public static String safeText(String key, Object... values) {
ResourceBundle rb = currentResourceBundle();
final String message;
if (!rb.containsKey(key)) {
// If no key is present then use it direct
message = "Key '" + key + "' is not localised!";
} else {
// Must have the key to be here
message = rb.getString(key);
}
return MessageFormat.format(message, values);
}
/**
* @param contents The contents to join into a localised comma-separated list
* @param maxLength The maximum length of the result single string
* @return The localised comma-separated list with ellipsis appended if truncated
*/
public static String truncatedList(Collection<String> contents, int maxLength) {
Preconditions.checkNotNull("contents", "'contents' must be present");
Preconditions.checkState(maxLength > 0 && maxLength < 4096, "'maxLength' must be [1,4096]");
String joinedContents = Joiner
.on(Languages.safeText(MessageKey.LIST_COMMA) + " ")
.join(contents);
String ellipsis = Languages.safeText(MessageKey.LIST_ELLIPSIS);
// Determine the truncation point (if required)
int maxIndex = Math.min(joinedContents.length() - 1, maxLength - ellipsis.length() - 1);
if (maxIndex == joinedContents.length() - 1) {
// No truncation
return joinedContents;
} else {
// Apply truncation (with ellipsis)
return joinedContents.substring(0, maxIndex) + ellipsis;
}
}
/**
* <p>Package access only - external consumers should use safeText()</p>
*
* @return The resource bundle based on the current locale
*/
static ResourceBundle currentResourceBundle() {
return ResourceBundle.getBundle(BASE_NAME, currentLocale());
}
/**
* @return The component orientation based on the current locale
*/
public static ComponentOrientation currentComponentOrientation() {
return ComponentOrientation.getOrientation(Languages.currentLocale());
}
/**
* @return True if text is to be placed left to right (standard Western language presentation)
*/
public static boolean isLeftToRight() {
return ComponentOrientation.getOrientation(currentLocale()).isLeftToRight();
}
}