Translate pages

This commit is contained in:
Andras Schmelczer 2026-04-04 09:47:18 +01:00
parent a7aaf5effa
commit 96402228e3
49 changed files with 1458 additions and 926 deletions

View file

@ -1,4 +1,6 @@
import { useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { ts } from '../../i18n/server';
import { useCollapsibleGroups } from '../../hooks/useCollapsibleGroups';
import { trackEvent } from '../../lib/analytics';
import type { POICategoryGroup } from '../../types';
@ -26,6 +28,7 @@ export default function POIPane({
onNavigateToSource,
onClose,
}: POIPaneProps) {
const { t } = useTranslation();
const [searchTerm, setSearchTerm] = useState('');
const [isGroupExpanded, toggleCollapse] = useCollapsibleGroups();
const [showInfo, setShowInfo] = useState(false);
@ -90,12 +93,12 @@ export default function POIPane({
<div className="flex-shrink-0 px-3 pt-3 pb-2">
<div className="flex items-center gap-2">
<span className="text-xs font-semibold text-warm-500 dark:text-warm-400 uppercase tracking-wide">
POIs
{t('poiPane.pois')}
</span>
<span className="text-xs text-warm-400 dark:text-warm-500">
{selectedCount}/{allCategories.length}
</span>
<IconButton onClick={() => setShowInfo(true)} title="Data source info">
<IconButton onClick={() => setShowInfo(true)} title={t('poiPane.dataSourceInfo')}>
<InfoIcon />
</IconButton>
<div className="flex gap-1 ml-auto items-center">
@ -103,19 +106,19 @@ export default function POIPane({
onClick={selectAll}
className="px-2 py-0.5 text-xs rounded border border-warm-300 dark:border-warm-700 text-warm-600 dark:text-warm-400 hover:bg-warm-50 dark:hover:bg-warm-700"
>
All
{t('common.all')}
</button>
<button
onClick={selectNone}
className="px-2 py-0.5 text-xs rounded border border-warm-300 dark:border-warm-700 text-warm-600 dark:text-warm-400 hover:bg-warm-50 dark:hover:bg-warm-700"
>
None
{t('common.none')}
</button>
{onClose && (
<button
onClick={onClose}
className="ml-1 p-0.5 text-warm-400 hover:text-warm-700 dark:hover:text-warm-300"
title="Close"
title={t('common.close')}
>
<CloseIcon className="w-4 h-4" />
</button>
@ -125,12 +128,12 @@ export default function POIPane({
{showInfo && (
<InfoPopup
title="Points of Interest"
title={t('poiPane.pointsOfInterest')}
onClose={() => setShowInfo(false)}
sourceLink={
onNavigateToSource
? {
label: 'View data source',
label: t('common.viewDataSource'),
onClick: () => {
onNavigateToSource('osm-pois');
setShowInfo(false);
@ -140,8 +143,7 @@ export default function POIPane({
}
>
<p className="text-sm text-warm-700 dark:text-warm-300 mb-4 leading-relaxed">
Sourced from OpenStreetMap. Covers public transport stops, shops, restaurants,
healthcare, leisure, and more. Updated regularly with complete category coverage.
{t('poiPane.poiDescription')}
</p>
</InfoPopup>
)}
@ -152,7 +154,7 @@ export default function POIPane({
<SearchInput
value={searchTerm}
onChange={setSearchTerm}
placeholder="Search categories..."
placeholder={t('poiPane.searchCategories')}
/>
</div>
{filteredGroups.map((group) => {
@ -171,7 +173,7 @@ export default function POIPane({
<ChevronIcon direction="right" className="w-3 h-3" />
</button>
<PillToggle
label={group.name}
label={ts(group.name)}
active={allInGroupSelected}
indeterminate={someInGroupSelected}
onClick={() => toggleGroup(group.name)}
@ -187,7 +189,7 @@ export default function POIPane({
{group.categories.map((category) => (
<PillToggle
key={category}
label={category}
label={ts(category)}
active={selectedCategories.has(category)}
onClick={() => toggleCategory(category)}
size="xs"