This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.
Internationalization (i18n)
The split is clear: formatting is automatic (LocaleFormats), text translation is manual
(you). Knowing which is which avoids hunting for an API that doesn’t exist.
Automatic formatting — LocaleFormats
LocaleFormats (in dev.crossfly.util) concentrates the locale-sensitive separators and formats, and
is respected by DatePicker/TimePicker/currency masks automatically:
| Field | Type | Controls |
|---|---|---|
dateFormat |
UIConstants.DateFormat |
date order (DMY/MDY/YMD) |
dateSeparator |
char |
date separator (/, -, .) |
timeSeparator |
char |
time separator (:) |
is24Hour |
boolean |
12h vs 24h |
decimalSeparator |
char |
decimal (, or .) |
thousandsSeparator |
char |
thousands |
weekStart |
byte |
first day of the week |
LocaleFormats.decimalSeparator = ',';
LocaleFormats.thousandsSeparator = '.';
LocaleFormats.is24Hour = true;
// from here on, the currency mask and the pickers already format in the pt-BR standard
Text translation — manual
There is no built-in string catalog. Externalize your text (your own Map/enum) and swap it
according to the language:
enum Idioma { PT, EN }
static Idioma idioma = Idioma.PT;
static final Map<String, Map<Idioma,String>> T = Map.of(
"salvar", Map.of(Idioma.PT, "Salvar", Idioma.EN, "Save"),
"cancelar", Map.of(Idioma.PT, "Cancelar", Idioma.EN, "Cancel")
);
static String t(String chave) { return T.get(chave).get(idioma); }
// usage:
new Button(t("salvar"));
Month/day names and picker labels are public fields that you reassign to localize.
Why the layout already helps
Layouts based on fraction/Relative tolerate text of different lengths across languages (“Salvar”
vs. “Enregistrer”) without breaking — another gain from not using fixed widths.
Best practices
- Configure
LocaleFormatsonce at bootstrap according to the user’s locale. - Externalize all visible text from the start (retrofitting later is expensive).
- Test the “widest” languages to make sure the layout accommodates them.
Common mistakes
- Looking for a built-in string/
R.stringsystem — it doesn’t exist; build your own. - Hardcoding
/in the date instead of usingLocaleFormats.dateSeparator.