La Raya · app (2): idioma compartido y construir sobre una API que cambia bajo tus pies

Publicado el 13/06/2026

La app de La Raya tuvo que crecer con dos incomodidades simultáneas: es bilingüe por naturaleza (frontera España-Portugal, más inglés para visitantes) y se construía sobre un backend que aún cambiaba de forma. Esta entrada va de cómo domesticar ambas.

El idioma, de verdad y en todas partes

El backend sirve el contenido en el idioma que le pidas mediante una cabecera. La parte de la app era que ese idioma fuera global y coherente: que elegirlo en un sitio afectara a todas las pantallas, y que el contenido se actualizara al cambiarlo.

Lo resolví con un contexto de idioma (LangContext) que guarda la preferencia de forma persistente y la inyecta en cada petición (la cabecera X-Accept-Language). El truco que faltaba: al cambiar de idioma, invalidar la caché de React Query para forzar el refetch. Sin eso, cambiabas a portugués y seguías viendo lo cacheado en español hasta que algo expiraba. Un picker de idioma (es/pt/en) en el perfil cierra el círculo.

Un picker de localidad que no estorba

Otra pieza de UX: filtrar por localidad. La primera versión era un desplegable normal; acabó siendo un chip + modal con búsqueda, porque la lista de pueblos es larga y un selector plano es incómodo. Pequeño cambio, gran diferencia al usarlo con una mano en el autobús.

Construir sobre arena: adaptarse a una API viva

Esto fue lo más realista del proceso. Mientras yo montaba listados y detalles, el backend seguía evolucionando: cambiaban campos, aparecían filtros (ordenar por fecha ascendente/descendente), se añadían recintos. Hubo más de un commit del tipo "adaptar el frontend al API actual".

Lecciones de construir contra un objetivo móvil:

  • Centraliza el cliente API (un único lib/api.ts con axios, interceptores y los endpoints por dominio). Cuando el backend cambia, tocas un sitio, no veinte.
  • Tipa las respuestas (TypeScript). Si el tipo no incluye un campo, la app lo descarta en silencio — un clásico que muerde callado. Mantener los tipos al día con la API te ahorra bugs invisibles.
  • Ordena igual que el backend. Hubo un baile con "próximos eventos": que la app pidiera ordering=fecha_inicio para que el más cercano saliera primero, en sintonía con lo que decidía el servidor. Cuando cliente y servidor discrepan en el orden, el usuario ve cosas raras.

La URL del API: hornearla en el build

Un detalle que parece tonto y no lo es: la app necesita saber a qué backend hablar, y eso cambia entre local y producción. La solución fue inyectar EXPO_PUBLIC_API_URL en tiempo de build (como argumento de construcción), de modo que cada binario sabe a dónde apunta sin configuración en runtime. (Esto volvería a darme guerra más adelante con los builds de release, pero esa es otra entrada.)

Lo que me llevo

  • El idioma es estado global, trátalo como tal. Un contexto + invalidación de caché al cambiarlo evita el clásico "lo cambié pero sigue en el idioma anterior".
  • Una API que cambia no es un problema si tu cliente está centralizado y tipado. Un único punto de contacto y tipos al día convierten un cambio de backend en un diff pequeño, no en una cacería.
  • Sintoniza orden y filtros con el servidor. Las discrepancias cliente/servidor en ordenación son bugs de percepción difíciles de depurar.
  • La configuración del entorno es parte del producto. Saber a qué API hablas (y hornearlo en el build) evita despliegues "que apuntan a localhost" en producción.

Con el idioma y la API domados, me metí en una función vistosa que luego reconsideré entera: la geolocalización para ordenar por cercanía. La próxima entrada cuenta por qué la añadí… y por qué acabé quitándola.