# Internacionalización (i18n)

> LocaleFormats se encarga del formato; la traducción de texto es manual — dónde ayuda el framework y dónde no.

Source: https://crossfly.dev/es/docs/best-practices/internacionalizacao — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Internacionalización (i18n)

La división es clara: **el formato es automático** (`LocaleFormats`), **la traducción de texto es manual**
(tú). Saber dónde queda cada una evita buscar una API que no existe.

## Formato automático — `LocaleFormats`
`LocaleFormats` (en `dev.crossfly.util`) concentra los separadores y formatos sensibles al locale, y es
respetado por `DatePicker`/`TimePicker`/máscara de moneda **automáticamente**:
| Campo | Tipo | Controla |
|---|---|---|
| `dateFormat` | `UIConstants.DateFormat` | orden de la fecha (DMY/MDY/YMD) |
| `dateSeparator` | `char` | separador de fecha (`/`, `-`, `.`) |
| `timeSeparator` | `char` | separador de hora (`:`) |
| `is24Hour` | `boolean` | 12h vs 24h |
| `decimalSeparator` | `char` | decimal (`,` o `.`) |
| `thousandsSeparator` | `char` | millar |
| `weekStart` | `byte` | primer día de la semana |

```java
LocaleFormats.decimalSeparator = ',';
LocaleFormats.thousandsSeparator = '.';
LocaleFormats.is24Hour = true;
// a partir de aquí, la máscara de moneda y los pickers ya formatean en el estándar pt-BR
```

## Traducción de texto — manual
**No hay catálogo de strings incorporado.** Externaliza tus textos (un `Map`/enum propio) y cámbialos
según el idioma:
```java
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); }

// uso:
new Button(t("salvar"));
```
Los nombres de meses/días y las etiquetas de los pickers son **campos públicos** que reasignas para localizar.

## Por qué el layout ya ayuda
Los layouts por **fracción/`Relative`** toleran textos de longitudes diferentes entre idiomas ("Salvar" vs
"Enregistrer") sin romperse — otra ventaja de no usar anchos fijos.

## Buenas prácticas
- Configura `LocaleFormats` **una vez** en el bootstrap según el locale del usuario.
- Externaliza **todo** el texto visible desde el inicio (adaptarlo después es caro).
- Prueba los idiomas más "anchos" para garantizar que el layout los admite.

## Errores comunes
- Buscar un sistema de strings/`R.string` incorporado — no existe; haz el tuyo.
- Hardcodear `/` en la fecha en vez de usar `LocaleFormats.dateSeparator`.

## Ver también
- [DatePicker](/docs/ui/widgets/datepicker) · [Máscaras y teclados](/docs/ui/forms-and-input/masks-and-keyboards)
