blob: 1bca6bf8ddd87dfc099673a644fa51fb9d853077 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2015 Dirk Fauth and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Dirk Fauth <dirk.fauth@gmail.com> - initial API and implementation
* Ragnar Nevries <r.eclipse@nevri.es> - Bug 458798
******************************************************************************/
package org.eclipse.e4.core.internal.services;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* Wrapper class for accessing translations out of a {@link ResourceBundle}.
*
* @author Dirk Fauth
*
*/
public class ResourceBundleTranslationProvider {
/**
* The {@link ResourceBundle} to use for translations.
*/
private ResourceBundle resourceBundle;
/**
*
* @param resourceBundle
* The {@link ResourceBundle} to use for translations. Can be <code>null</code>,
* which will lead to simply return the key modified by prefixing and suffixing it
* with "!" when calling translate(String).
*/
public ResourceBundleTranslationProvider(ResourceBundle resourceBundle) {
this.setResourceBundle(resourceBundle);
}
/**
* Tries to retrieve the translation value for the given key out of the {@link ResourceBundle}
* set to this {@link ResourceBundleTranslationProvider}. If there is no {@link ResourceBundle}
* set or there is no translation found for the given key, the key itself prefixed and suffixed
* with "!" will be returned to indicate that there is no translation found.
* <p>
* This implementation also supports the usage of dot separation for property keys. As in Java
* variables can not be separated with a dot, the underscore needs to be used for separation of
* the variable. This will be replaced automatically to a dot, if there is no translation found
* with an underscore as separator.
* </p>
* This implementation also supports camel cased member variables to match the appropriate
* property keys. As a result, all combinations of replacing camel cased strings by
* their "underscorified" version and replacing underscores by dots are considered. The order
* is shown by the following example:
* <p>
* Let the property key to translate be <i>camelCase_Subtree</i>. Then the
* {@link ResourceBundle} is browsed for the following keys (in that order):
* </p>
* <ol>
* <li>camelCase_Subtree</li>
* <li>camel_case__subtree</li>
* <li>camel.case..subtree</li>
* <li>camelCase.Subtree</li>
* <li>camel_case._subtree</li>
* </ol>
*
*
* @param key
* The key of the requested translation property.
* @return The translation for the given key or the key itself prefixed and suffixed with "!" to
* indicate that there is no translation available for the given key.
*/
public String translate(String key) {
String result = translate_rec(key);
if (result != null) {
return result;
} else {
return "!" + key + "!"; //$NON-NLS-1$ //$NON-NLS-2$
}
}
private String translate_rec(String key) {
String result = null;
try {
if (this.resourceBundle != null) {
result = this.resourceBundle.getString(key);
}
} catch (MissingResourceException e) {
// key was not found as is, check if it is camel cased or contains
// underscores
// try to de-camel-casify and recurse
if (key.matches(".*[A-Z].*")) { //$NON-NLS-1$
result = translate_rec(underscorify(key));
}
// if no succes, try to de-underscorify and recurse
if (result == null && key.contains("_")) { //$NON-NLS-1$
result = translate_rec(key.replace('_', '.')); //$NON-NLS-1$ //$NON-NLS-2$
}
}
return result;
}
/**
* @return The {@link ResourceBundle} that is used for translations.
*/
public ResourceBundle getResourceBundle() {
return resourceBundle;
}
/**
* @param resourceBundle
* The {@link ResourceBundle} to use for translations.
*/
public void setResourceBundle(ResourceBundle resourceBundle) {
this.resourceBundle = resourceBundle;
}
/**
* This method is used to create a underscorified key out of a camel cased String.
* <p>
* Note: This method is introduced to support Java Naming Conventions for member variables,
* which says that member variables should be camel cased. See <a href=
* "http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-135099.html#367"
* > Naming Conventions</a>.
*
* @param key
* The possible camel cased key that needs to be underscorified.
* @return The underscorified key.
*/
public static String underscorify(String key) {
if (key == null || key.isEmpty()) {
return key;
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < key.length(); i++) {
if (Character.isUpperCase(key.charAt(i))) {
result.append("_").append(Character.toLowerCase(key.charAt(i))); //$NON-NLS-1$
} else {
result.append(key.charAt(i));
}
}
return result.toString();
}
}