Skip to content
CrossFly is 100% open sourceFollow us on GitHub
CrossFlyCrossFly
Get started

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 LocaleFormats once 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.string system — it doesn’t exist; build your own.
  • Hardcoding / in the date instead of using LocaleFormats.dateSeparator.

See also

Was this page helpful?