aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/app/routes/settings.tsx
diff options
context:
space:
mode:
authorAriel Costas Guerrero <ariel@costas.dev>2025-06-24 16:14:28 +0200
committerAriel Costas Guerrero <ariel@costas.dev>2025-06-24 16:14:28 +0200
commitecb73e1684b42265af3f8d93541600e4d0f9c414 (patch)
tree26e413973b32de0367aa06cfc0df329c67733821 /src/frontend/app/routes/settings.tsx
parentf65b4e1e0d5648038823962349279be4badc68ed (diff)
Implement i18n
Closes #18
Diffstat (limited to 'src/frontend/app/routes/settings.tsx')
-rw-r--r--src/frontend/app/routes/settings.tsx69
1 files changed, 40 insertions, 29 deletions
diff --git a/src/frontend/app/routes/settings.tsx b/src/frontend/app/routes/settings.tsx
index b5e91f1..e657c03 100644
--- a/src/frontend/app/routes/settings.tsx
+++ b/src/frontend/app/routes/settings.tsx
@@ -1,64 +1,75 @@
import { useApp } from "../AppContext";
import "./settings.css";
+import { useTranslation } from "react-i18next";
export default function Settings() {
+ const { t, i18n } = useTranslation();
const { theme, setTheme, tableStyle, setTableStyle, mapPositionMode, setMapPositionMode } = useApp();
return (
<div className="page-container">
- <h1 className="page-title">Sobre UrbanoVigo Web</h1>
+ <h1 className="page-title">{t('about.title')}</h1>
<p className="about-description">
- Aplicación web para encontrar paradas y tiempos de llegada de los autobuses
- urbanos de Vigo, España.
+ {t('about.description')}
</p>
<section className="settings-section">
- <h2>Ajustes</h2>
+ <h2>{t('about.settings')}</h2>
<div className="settings-content-inline">
- <label htmlFor="theme" className="form-label-inline">Modo:</label>
- <select id="theme" className="form-select-inline" value={theme} onChange={(e) => setTheme(e.target.value as "light" | "dark")}>
- <option value="light">Claro</option>
- <option value="dark">Oscuro</option>
+ <label htmlFor="theme" className="form-label-inline">{t('about.theme')}</label>
+ <select id="theme" className="form-select-inline" value={theme} onChange={(e) => setTheme(e.target.value as "light" | "dark")}>
+ <option value="light">{t('about.theme_light')}</option>
+ <option value="dark">{t('about.theme_dark')}</option>
</select>
</div>
<div className="settings-content-inline">
- <label htmlFor="tableStyle" className="form-label-inline">Estilo de tabla:</label>
- <select id="tableStyle" className="form-select-inline" value={tableStyle} onChange={(e) => setTableStyle(e.target.value as "regular" | "grouped")}>
- <option value="regular">Mostrar por orden</option>
- <option value="grouped">Agrupar por línea</option>
+ <label htmlFor="tableStyle" className="form-label-inline">{t('about.table_style')}</label>
+ <select id="tableStyle" className="form-select-inline" value={tableStyle} onChange={(e) => setTableStyle(e.target.value as "regular" | "grouped")}>
+ <option value="regular">{t('about.table_style_regular')}</option>
+ <option value="grouped">{t('about.table_style_grouped')}</option>
</select>
</div>
<div className="settings-content-inline">
- <label htmlFor="mapPositionMode" className="form-label-inline">Posición del mapa:</label>
- <select id="mapPositionMode" className="form-select-inline" value={mapPositionMode} onChange={e => setMapPositionMode(e.target.value as 'gps' | 'last')}>
- <option value="gps">Posición GPS</option>
- <option value="last">Donde lo dejé</option>
+ <label htmlFor="mapPositionMode" className="form-label-inline">{t('about.map_position_mode')}</label>
+ <select id="mapPositionMode" className="form-select-inline" value={mapPositionMode} onChange={e => setMapPositionMode(e.target.value as 'gps' | 'last')}>
+ <option value="gps">{t('about.map_position_gps')}</option>
+ <option value="last">{t('about.map_position_last')}</option>
+ </select>
+ </div>
+ <div className="settings-content-inline">
+ <label htmlFor="language" className="form-label-inline">Idioma:</label>
+ <select
+ id="language"
+ className="form-select-inline"
+ value={i18n.language}
+ onChange={e => i18n.changeLanguage(e.target.value)}
+ >
+ <option value="es-ES">Español</option>
+ <option value="gl-ES">Galego</option>
+ <option value="en-GB">English</option>
</select>
</div>
<details className="form-details">
- <summary>¿Qué significa esto?</summary>
- <p>
- La tabla de horarios puede mostrarse de dos formas:
- </p>
+ <summary>{t('about.details_summary')}</summary>
+ <p>{t('about.details_table')}</p>
<dl>
- <dt>Mostrar por orden</dt>
- <dd>Las paradas se muestran en el orden en que se visitan. Aplicaciones como Infobus (Vitrasa) usan este estilo.</dd>
- <dt>Agrupar por línea</dt>
- <dd>Las paradas se agrupan por la línea de autobús. Aplicaciones como iTranvias (A Coruña) o Moovit (más o menos) usan este estilo.</dd>
+ <dt>{t('about.table_style_regular')}</dt>
+ <dd>{t('about.details_regular')}</dd>
+ <dt>{t('about.table_style_grouped')}</dt>
+ <dd>{t('about.details_grouped')}</dd>
</dl>
</details>
</section>
- <h2>Créditos</h2>
+ <h2>{t('about.credits')}</h2>
<p>
<a href="https://github.com/arielcostas/urbanovigo-web" className="about-link" rel="nofollow noreferrer noopener">
- Código en GitHub
+ {t('about.github')}
</a> -
- Desarrollado por <a href="https://www.costas.dev" className="about-link" rel="nofollow noreferrer noopener">
+ {t('about.developed_by')} <a href="https://www.costas.dev" className="about-link" rel="nofollow noreferrer noopener">
Ariel Costas
</a>
</p>
<p>
- Datos obtenidos de <a href="https://datos.vigo.org" className="about-link" rel="nofollow noreferrer noopener">datos.vigo.org</a> bajo
- licencia <a href="https://opendefinition.org/licenses/odc-by/" className="about-link" rel="nofollow noreferrer noopener">Open Data Commons Attribution License</a>
+ {t('about.data_source_prefix')} <a href="https://datos.vigo.org" className="about-link" rel="nofollow noreferrer noopener">datos.vigo.org</a> {t('about.data_source_middle')} <a href="https://opendefinition.org/licenses/odc-by/" className="about-link" rel="nofollow noreferrer noopener">Open Data Commons Attribution License</a>
</p>
</div>
)