Java tutorial
import java.text.Format; import java.text.MessageFormat; import java.util.Locale; import java.util.ResourceBundle; /** * Internationalisation (I18N) helper * @author eliott bartley */ public class I18N { private I18N() { } /** * Given a message and parameters, resolve all message's parameter * placeholders with the parameter value. The firstParam can change which * parameter relates to {0} placeholder in the message, and all increment * from this index. If any of the parameters also have placeholders, this * recursively calls itself to fill their placeholders, setting the * firstParam to the index following all parameters that are used by the * current message so params must be in the order p0..pN, p00..p0N..pMN, * p000..p00N..p0MN..pLMN... where each additional index is for nested * placeholders (ones in params) and assumes every message/param contains * N M L placeholders; any that don't contain placeholders can have their * pXXX.. taken out, so long as the order of remaining params don't change * @param message Message to format * @param firstParam Index of parameter that relates to {0} placeholder, * all parameters following this one relate to incrementing placeholders * @param params The parameters used to fill the placeholders * @return Message with all placeholders filled with relative parameters */ private static String formatMessage(String message, int firstParam, Object[] params) { // Only need to do any formatting if there are parameters to do the // formatting with. If there are none, the message input is returned // unmodified if (params != null && firstParam < params.length) { MessageFormat parser; Locale locale = Locale.getDefault(); Format[] formats; // Set up parser = new MessageFormat(""); parser.setLocale(locale); parser.applyPattern(message); // Used only to count how many parameters are needed by this message formats = parser.getFormatsByArgumentIndex(); // Recursively format the parameters used by this message for (int paramIndex = 0; paramIndex < formats.length; paramIndex++) if (params[firstParam + paramIndex] instanceof String) params[firstParam + paramIndex] = formatMessage(params[firstParam + paramIndex].toString(), firstParam + formats.length, params); // Format the message using the formatted parameters message = parser.format(getParams(params, firstParam, firstParam + formats.length)); } return message; } /** * MessageFormat.format always matches the placeholder's index directly to * the param array index, but because placeholders can be nested, the * zeroth placeholder may not match the zeroth array element, so this * method copies the array so that only the required array elements are * present, and start from the zeroth element * @param params Complete param array * @param firstParam First element that will be used in complete param array * @param lastParam Last element that will be used in complete param array * @return Param array containing just the elements from * firstParam..lastParam-1. If lastParam is less or equal to firstParam, * null is returned rather than an empty array */ private static Object[] getParams(Object[] params, int firstParam, int lastParam) { Object[] newParams = null; if (firstParam < lastParam) { newParams = new Object[lastParam - firstParam]; for (int i = firstParam; i < lastParam; i++) newParams[i - firstParam] = params[i]; } return newParams; } }