ecosystem-wikicómo extender los templates sin romper sus convenciones
‹ todas las recipes

Tema e i18n

template-expo
último cambio 2026-09-25

Las dos convenciones más fáciles de romper sin darse cuenta, porque nada falla al romperlas: un color a pelo funciona, y un texto en castellano dentro de un componente también.

Tema: nada de valores literales

Todo vive en constants/theme.ts y se importa:

import { Fonts, KawaiiPalette, Radius, Spacing } from '@/constants/theme';
Export Qué es
KawaiiPalette La paleta de marca — sakura, matcha, sumi, paper…
Colors Neutros claro/oscuro, reservados para cromo del sistema
Spacing Escala de espaciado: half, one … six
Radius sm, md, lg, pill
Fonts Familias por plataforma, con display para la tipografía propia

Hay dos paletas y no se mezclan, como dice el comentario del fichero: KawaiiPalette es la identidad visual de las pantallas; Colors son los neutros claro/oscuro para cromo del sistema.

No escribas un #hex ni un número de espaciado en un StyleSheet. Si el valor que necesitas no está en la escala, añádelo a la escala.

La escala es deliberadamente corta —siete pasos de espaciado, cuatro radios— y eso es lo que hace que la app se vea consistente sin que nadie lo vigile. Un padding: 13 no está mal por feo: está mal porque el siguiente pondrá 14.

También hay dos valores de plataforma que conviene usar en vez de recalcularlos: BottomTabInset y MaxContentWidth.

i18n: ningún texto en el componente

Tres idiomas —es, en, ca— con un JSON por idioma en i18n/locales/, y en el componente:

const { t } = useTranslation();
// ...
<Text>{t('settings.language')}</Text>

Una clave nueva se añade a los tres ficheros a la vez. Si falta en uno, cae al castellano por el fallbackLng y nadie lo nota hasta que alguien usa la app en inglés.

Las claves se agrupan por pantalla o área (settings.*, pets.*), que es lo que permite encontrar lo que hay que cambiar sin buscar el texto.

El idioma se resuelve antes del primer render

initI18n() lo decide en este orden: elección guardada del usuario → idioma del dispositivo → castellano. Y se guarda en SecureStore a propósito, para que el siguiente arranque sea instantáneo sin esperar a que /settings responda por red.

Dos cosas que se siguen de ahí:

Al cambiar el idioma

Hay que hacer las dos cosas: decírselo a i18next y persistirlo. Si solo cambias lo primero, la elección se pierde al cerrar la app; si solo lo segundo, la pantalla no se traduce hasta reiniciar.