Skip to content

Conversation

@samirbrkic
Copy link

🌍 Multi-Language Support (i18n) Framework

This PR introduces a comprehensive internationalization system for ITFlow.

Features

  • 🔧 Core i18n engine with automatic language detection
  • 🌐 Language switcher UI component
  • 🔒 Security: Whitelist-based locale validation
  • 📝 Translation files for German (de_DE) and English (en_US)
  • ✅ Demo: 3 modules fully translated (Tickets, Clients, Common UI)

Architecture

  • Non-intrusive: No changes to core files
  • Extensible: Easy to add new languages
  • Session-based: User language preference persisted
  • Fallback: Defaults to English if translation missing

Demo Modules

  • ✅ Tickets module (list + details)
  • ✅ Clients module (list + navigation)
  • ✅ Common UI strings (navigation, buttons, labels)

Files

  • includes/i18n.php - Core translation engine
  • includes/language_switcher.php - Language selector UI
  • lang/de_DE/ - German translations
  • lang/en_US/ - English translations

Next Steps (Future PRs)

  • Phase 2: Translate additional modules (Invoices, Assets, etc.)
  • Phase 3: Add more languages (FR, ES, IT, etc.)
  • Phase 4: Admin UI for translation management

johnnyq and others added 16 commits November 8, 2025 13:47
Merge Develop into Master for v25.11.1 release
Develop to Master for 25.12 release
Develop to Master for 25.12.1 Maint Release
- Add locale format validation (regex) to prevent path traversal attacks
- Add htmlspecialchars() to escape user-controlled output and prevent XSS
- Ensure locale format matches expected pattern (e.g., en_US, de_DE)
- Escape all language names before HTML output
- Replace regex validation with hardcoded whitelist of allowed locales
- Prevents path injection by never using unsanitized user input in paths
- Fix XSS vulnerability in redirect URL by using PHP_SELF instead of REQUEST_URI
- Update i18n_get_available_languages() to use whitelist instead of directory scan
- Add clear documentation for adding new languages to whitelist

Security improvements:
- Line 90 (i18n.php): Use whitelisted locale value, not user input
- Line 32 (language_switcher.php): Sanitize redirect URL with htmlspecialchars
- Eliminates all path traversal and XSS attack vectors
- Create lang/en_US/tickets.php with 80+ ticket-related translations
- Create lang/de_DE/tickets.php with German translations
- Internationalize tickets.php page:
  - Header (Tickets, Open, Closed counts)
  - Actions (New Ticket, Export)
  - Search and filters
  - View options (List, Kanban)
  - My Tickets dropdown
  - Unassigned button
  - Bulk actions menu (Assign, Category, Priority, Reply, Project, Merge, Resolve)
  - Advanced filters (Date range, Status, Assigned to)

Translations cover:
- Page navigation and controls
- Bulk operations
- Filter labels and placeholders
- Status indicators
- User-facing text
- Rename second occurrence to 'ticket_status_label' to avoid array key collision
- Fixes SonarQube reliability warning about overwritten array values
- Create lang/en_US/clients.php with 75+ client-related translations
- Create lang/de_DE/clients.php with German translations
- Internationalize clients.php page:
  - Header (Clients/Leads toggle)
  - Actions (New, Import, Export)
  - Search placeholders
  - Client/Lead filter buttons
  - Archived toggle
  - Bulk actions menu (Open Tickets, Set Hourly Rate, Set Industry, Set Referral, Assign Tags, Send Email, Archive/Restore)

Translations cover:
- Client vs Lead terminology
- Filter and navigation controls
- Bulk operations
- Status indicators
- User-facing labels

No duplicate keys detected
- Add missing translations: 'ticket', 'billable', 'not_assigned'
- Translate all table column headers in ticket_list.php
- Translate 'Not Assigned' status text
- Now displays: Ticket, Subject, Client, Contact, Billable, Priority, Status, Assigned, Last Response, Created in selected language

No duplicate keys detected
- Add helper functions translatePriority() and translateStatus() to map DB values
- Translate hardcoded strings: Never, Yes, No, Invoiced
- Priority values now translated via priority_* keys from common.php
- Status values now translated via status_* keys from common.php
- Add missing translations: 'never', 'invoiced' to common module

Cell values now fully internationalized
- Added translations to lang/en_US/tickets.php and lang/de_DE/tickets.php:
  - ticket_details, created_by, category, user, closed
  - tasks, tasks_completed, view
  - mark_all_complete, mark_all_incomplete, delete_all
- Translated all labels in agent/ticket.php:
  - Updated, Created, Created by, Source, Category
  - First Response (FR/EA), Time worked, Resolved
  - Closed by, Closed, Feedback
  - Download, View links for attachments
  - Tasks card header and actions
  - Tasks Completed progress bar
- Added translatePriority() helper function to ticket.php
- Priority badges now display translated values (Low/Medium/High)
- Maintains consistency with ticket_list.php translation approach
- Removed duplicate keys: closed, view, updated, category, ticket_details
- Keys now only defined once in 'Ticket Detail Page' section
- Prevents SonarQube 'Duplicate literal' warnings
- Maintains all functionality with single key definitions
- Added translateStatus() helper function alongside translatePriority()
- Fixes 'Call to undefined function translateStatus()' fatal error
- Ticket detail page now loads correctly
- Fixed 'time_worked' translation: 'Bearbeitungszeit' → 'Arbeitszeit' (clearer meaning)
- Added translations: not_assigned, internal_note, public_comment_email, public_comment
- Added translations: redact, edit, archive, created_label, edited
- Added translations: type_response, hours_abbr, minutes_abbr, seconds_abbr, create_task
- Added 'client' and 'submit' to common.php
- Translated all remaining strings in ticket.php:
  - 'Not Assigned' badge
  - Reply form radio buttons (Internal Note, Public Comment & Email, Public Comment)
  - Placeholder text ('Type a response', 'Create Task')
  - Time input placeholders (Hrs, Mins, Secs)
  - Reply actions dropdown (Redact, Edit, Archive)
  - Reply timestamp labels (Created, Edited, Internal)
  - Submit button
- Removed duplicate keys from language files
- Added 22 translations to lang/en_US/clients.php and lang/de_DE/clients.php:
  - back, overview, support, recurring_tickets, projects
  - vendors, calendar, documentation, licenses, credentials
  - networks, racks, certificates, domains, services, files
  - billing, invoices, recurring_invoices, quotes, payments, trips
- Translated all menu items in agent/includes/client_side_nav.php:
  - Back link with client abbreviation
  - Overview, Contacts, Locations
  - SUPPORT section (Tickets, Recurring Tickets, Projects)
  - Vendors, Calendar
  - DOCUMENTATION section (Assets, Licenses, Credentials, Networks, Racks, Certificates, Domains, Services, Files)
  - BILLING section (Invoices, Recurring Invoices, Quotes, Payments, Trips)
- Section headers now uppercase using strtoupper(__())
- All navigation items now fully translated for client detail pages
@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 8, 2026

@wrongecho wrongecho changed the base branch from master to develop January 8, 2026 09:06
@samirbrkic samirbrkic closed this Jan 8, 2026
@samirbrkic samirbrkic deleted the i18n-phase1-framework branch January 8, 2026 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants