Given a message and parameters, resolve all message's parameter placeholders with the parameter value.
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;
}
}
Related examples in the same category