Implement shared packages (tasks 2.1-2.6)
- @trails-cool/types: Route, Activity, Waypoint, RouteVersion, RouteMetadata - @trails-cool/gpx: GPX parser (XML→waypoints/tracks/elevation) and generator with round-trip test, haversine distance, elevation gain/loss computation - @trails-cool/map: MapView (Leaflet + OSM/OpenTopoMap/CyclOSM layer switcher), RouteLayer (GeoJSON polyline rendering) - @trails-cool/ui: Button (primary/secondary/ghost), Input (with label/error), Card components with Tailwind styling - @trails-cool/i18n: react-i18next config with English + German translations, browser language detection, fallback to English All 13 unit tests pass. Both apps build successfully. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
325a4466d5
commit
2cfa5e54e7
23 changed files with 809 additions and 30 deletions
|
|
@ -2,6 +2,15 @@
|
|||
"name": "@trails-cool/i18n",
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./locales/*": "./src/locales/*"
|
||||
},
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts"
|
||||
"types": "./src/index.ts",
|
||||
"peerDependencies": {
|
||||
"react": ">=18",
|
||||
"i18next": ">=23",
|
||||
"react-i18next": ">=14"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,29 @@
|
|||
/**
|
||||
* Shared i18n configuration and translation strings for trails.cool
|
||||
* Uses react-i18next. Start with English + German.
|
||||
*/
|
||||
export {};
|
||||
import i18n from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import LanguageDetector from "i18next-browser-languagedetector";
|
||||
import en from "./locales/en";
|
||||
import de from "./locales/de";
|
||||
|
||||
export const defaultNS = "common";
|
||||
|
||||
export const resources = {
|
||||
en: { common: en.common, planner: en.planner, journal: en.journal },
|
||||
de: { common: de.common, planner: de.planner, journal: de.journal },
|
||||
} as const;
|
||||
|
||||
export function initI18n() {
|
||||
return i18n
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
resources,
|
||||
defaultNS,
|
||||
fallbackLng: "en",
|
||||
supportedLngs: ["en", "de"],
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export { i18n };
|
||||
|
|
|
|||
59
packages/i18n/src/locales/de.ts
Normal file
59
packages/i18n/src/locales/de.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
export default {
|
||||
common: {
|
||||
save: "Speichern",
|
||||
cancel: "Abbrechen",
|
||||
delete: "Löschen",
|
||||
edit: "Bearbeiten",
|
||||
close: "Schließen",
|
||||
loading: "Wird geladen...",
|
||||
error: "Etwas ist schiefgelaufen",
|
||||
},
|
||||
planner: {
|
||||
title: "trails.cool Planer",
|
||||
subtitle: "Gemeinsame Routenplanung",
|
||||
newSession: "Neue Sitzung",
|
||||
saveRoute: "Route speichern",
|
||||
exportGpx: "GPX exportieren",
|
||||
profile: "Routing-Profil",
|
||||
profiles: {
|
||||
trekking: "Wandern",
|
||||
bike: "Radfahren",
|
||||
shortest: "Kürzeste",
|
||||
},
|
||||
elevation: {
|
||||
gain: "Höhenmeter aufwärts",
|
||||
loss: "Höhenmeter abwärts",
|
||||
profile: "Höhenprofil",
|
||||
},
|
||||
},
|
||||
journal: {
|
||||
title: "trails.cool",
|
||||
subtitle: "Dein Outdoor-Aktivitäten-Tagebuch",
|
||||
routes: {
|
||||
title: "Routen",
|
||||
new: "Neue Route",
|
||||
edit: "Route bearbeiten",
|
||||
editInPlanner: "Im Planer bearbeiten",
|
||||
importGpx: "GPX importieren",
|
||||
exportGpx: "GPX exportieren",
|
||||
delete: "Route löschen",
|
||||
distance: "Strecke",
|
||||
elevationGain: "Höhenmeter",
|
||||
},
|
||||
activities: {
|
||||
title: "Aktivitäten",
|
||||
new: "Neue Aktivität",
|
||||
duration: "Dauer",
|
||||
linkToRoute: "Mit Route verknüpfen",
|
||||
createRouteFromActivity: "Route aus Aktivität erstellen",
|
||||
},
|
||||
auth: {
|
||||
login: "Anmelden",
|
||||
register: "Registrieren",
|
||||
logout: "Abmelden",
|
||||
email: "E-Mail",
|
||||
password: "Passwort",
|
||||
username: "Benutzername",
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
59
packages/i18n/src/locales/en.ts
Normal file
59
packages/i18n/src/locales/en.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
export default {
|
||||
common: {
|
||||
save: "Save",
|
||||
cancel: "Cancel",
|
||||
delete: "Delete",
|
||||
edit: "Edit",
|
||||
close: "Close",
|
||||
loading: "Loading...",
|
||||
error: "Something went wrong",
|
||||
},
|
||||
planner: {
|
||||
title: "trails.cool Planner",
|
||||
subtitle: "Collaborative route planning",
|
||||
newSession: "New Session",
|
||||
saveRoute: "Save Route",
|
||||
exportGpx: "Export GPX",
|
||||
profile: "Routing Profile",
|
||||
profiles: {
|
||||
trekking: "Hiking",
|
||||
bike: "Cycling",
|
||||
shortest: "Shortest",
|
||||
},
|
||||
elevation: {
|
||||
gain: "Elevation Gain",
|
||||
loss: "Elevation Loss",
|
||||
profile: "Elevation Profile",
|
||||
},
|
||||
},
|
||||
journal: {
|
||||
title: "trails.cool",
|
||||
subtitle: "Your outdoor activity journal",
|
||||
routes: {
|
||||
title: "Routes",
|
||||
new: "New Route",
|
||||
edit: "Edit Route",
|
||||
editInPlanner: "Edit in Planner",
|
||||
importGpx: "Import GPX",
|
||||
exportGpx: "Export GPX",
|
||||
delete: "Delete Route",
|
||||
distance: "Distance",
|
||||
elevationGain: "Elevation Gain",
|
||||
},
|
||||
activities: {
|
||||
title: "Activities",
|
||||
new: "New Activity",
|
||||
duration: "Duration",
|
||||
linkToRoute: "Link to Route",
|
||||
createRouteFromActivity: "Create Route from Activity",
|
||||
},
|
||||
auth: {
|
||||
login: "Log In",
|
||||
register: "Sign Up",
|
||||
logout: "Log Out",
|
||||
email: "Email",
|
||||
password: "Password",
|
||||
username: "Username",
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
Loading…
Add table
Add a link
Reference in a new issue