This commit extends the existing i18n system to fully support server-side translations
for users who have JavaScript disabled or are using the /table route directly.
Changes:
- Complete server-side Spanish (es-MX) translation support for /table route
- Language selector dropdown in table view with form-based locale switching
- URL parameter support (?locale=es-MX) for direct language selection
- Updated POST form handler to persist locale selection across submissions
- Proper locale detection and fallback for server-rendered pages
- Fixed language selector initialization timing in client-side JS
- Removed unused dependencies (canvas, sharp) to clean up package.json
- Added snowflake emoji to app name in both English and Spanish translations
The /table route now provides a complete non-JavaScript experience in both English
and Spanish, ensuring accessibility for all users regardless of their browser
capabilities or JavaScript preferences.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This major feature introduces complete internationalization architecture with Spanish (Mexico) as the first additional language:
## New Features:
- **I18n Architecture**: Complete client-side and server-side internationalization system
- **Spanish (Mexico) Support**: Full es-MX translations for all user-facing text
- **Language Selector**: Dynamic language switching UI component in header
- **API Endpoints**: RESTful endpoints for serving translations (/api/i18n)
- **Progressive Enhancement**: Language detection via Accept-Language header and cookies
## Technical Implementation:
- **Frontend**: Client-side i18n.js with automatic DOM translation and language selector
- **Backend**: Server-side i18n service with locale detection middleware
- **Build Process**: Automated copying of translation files to dist/ directory
- **Responsive Design**: Language selector integrated into header controls layout
## Files Added:
- public/i18n.js - Client-side internationalization library
- src/i18n/index.ts - Server-side i18n service
- src/i18n/locales/en.json - English translations
- src/i18n/locales/es-MX.json - Spanish (Mexico) translations
- src/routes/i18n.ts - API endpoints for translations
## Files Modified:
- package.json - Updated build process to include i18n files
- public/index.html - Added i18n attributes and language selector
- public/app.js - Integrated dynamic translation updates
- src/server.ts - Added locale detection middleware
- src/scss/pages/_index.scss - Language selector styling
This implementation supports easy addition of future languages and maintains backward compatibility while providing a seamless multilingual experience.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implement MapImageService using Mapbox Static Images API
- Add server-side /table route with HTML form submission
- Generate static map images with auto-fit positioning based on actual location coordinates
- Add progressive enhancement with noscript fallbacks and Basic View button
- Update map center coordinates to proper Grand Rapids location
- Add numbered pins with color coding (red for regular, orange for persistent reports)
- Remove server-side caching to ensure fresh map images
- Fix theme toggle icon centering in CSS mixins
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create public/utils.js with shared frontend utility functions
- Extract parseUTCDate, getTimeAgo, getTimeRemaining, getRemainingClass to utils.js
- Remove duplicate functions from admin.js, app-mapbox.js, app-google.js, and app.js
- Add utils.js script import to index.html and admin.html
- Add comprehensive JSDoc documentation for all utility functions
- Ensure consistent UTC timestamp parsing across all frontend scripts
This addresses Copilot AI feedback about function duplication across multiple frontend scripts.
Now all timestamp and time calculation logic is centralized in one maintainable module.
Benefits:
- Single source of truth for time-related utilities
- Easier maintenance and updates
- Consistent behavior across all frontend components
- Better code organization and documentation
- Reduced bundle size through deduplication
- Add parseUTCDate helper function to handle timestamp UTC parsing consistently
- Eliminates code duplication across getTimeAgo, getTimeRemaining, and expiry functions
- Applied to admin.js, app-mapbox.js, app-google.js, and app.js
- Ensures consistent UTC timezone handling throughout all frontend JavaScript
- Addresses Copilot AI feedback for better code maintainability and DRY principles
The parseUTCDate function handles the logic:
timestamp.includes('T') ? timestamp : timestamp + 'Z'
This ensures all timestamp parsing uses the same UTC interpretation logic.
- Created custom map markers with distinct colors and symbols:
- 🔒 Green circles with lock icon for persistent reports
- ⚠️ Red circles with warning icon for temporary reports
- Updated popup text to indicate persistent status
- Applied consistent styling to both MapBox and Nominatim versions
- Enhanced visual distinction between report types on the map