diff --git a/management/src/components/Layout.jsx b/management/src/components/Layout.jsx index b14c254..94f250a 100644 --- a/management/src/components/Layout.jsx +++ b/management/src/components/Layout.jsx @@ -1,8 +1,9 @@ import React from 'react' import { Outlet, NavLink, useLocation } from 'react-router-dom' -import { useTranslation } from 'react-i18next' +// import { useTranslation } from 'react-i18next' // Commented out until Docker rebuild import { useAuth } from '../contexts/AuthContext' import LanguageSelector from './common/LanguageSelector' +import { t } from '../utils/tempTranslations' // Temporary translation system import { HomeIcon, BuildingOfficeIcon, @@ -12,15 +13,15 @@ import { } from '@heroicons/react/24/outline' const Layout = () => { - const { t } = useTranslation() + // const { t } = useTranslation() // Commented out until Docker rebuild const { user, logout } = useAuth() const location = useLocation() const navigation = [ - { name: t('navigation.dashboard'), href: '/dashboard', icon: HomeIcon }, - { name: t('navigation.tenants'), href: '/tenants', icon: BuildingOfficeIcon }, - { name: t('navigation.users'), href: '/users', icon: UsersIcon }, - { name: t('navigation.system'), href: '/system', icon: CogIcon }, + { name: t('nav.dashboard'), href: '/dashboard', icon: HomeIcon }, + { name: t('nav.tenants'), href: '/tenants', icon: BuildingOfficeIcon }, + { name: t('nav.users'), href: '/users', icon: UsersIcon }, + { name: t('nav.system'), href: '/system', icon: CogIcon }, ] return ( @@ -76,7 +77,7 @@ const Layout = () => { diff --git a/management/src/pages/Dashboard.jsx b/management/src/pages/Dashboard.jsx index 76cc52f..3871222 100644 --- a/management/src/pages/Dashboard.jsx +++ b/management/src/pages/Dashboard.jsx @@ -1,5 +1,6 @@ import React, { useState, useEffect } from 'react' import api from '../services/api' +import { t } from '../utils/tempTranslations' // Temporary translation system import { BuildingOfficeIcon, UsersIcon, ServerIcon, ChartBarIcon } from '@heroicons/react/24/outline' const Dashboard = () => { @@ -38,26 +39,26 @@ const Dashboard = () => { const statCards = [ { - name: 'Total Tenants', + name: t('dashboard.totalTenants'), value: stats.tenants, icon: BuildingOfficeIcon, color: 'bg-blue-500' }, { - name: 'Total Users', + name: t('dashboard.totalUsers'), value: stats.users, icon: UsersIcon, color: 'bg-green-500' }, { - name: 'Active Sessions', + name: t('dashboard.activeSessions'), value: stats.activeSessions, icon: ChartBarIcon, color: 'bg-yellow-500' }, { - name: 'System Health', - value: stats.systemHealth === 'good' ? 'Good' : 'Issues', + name: t('dashboard.systemHealth'), + value: stats.systemHealth === 'good' ? t('dashboard.good') : t('dashboard.issues'), icon: ServerIcon, color: stats.systemHealth === 'good' ? 'bg-green-500' : 'bg-red-500' } @@ -74,8 +75,8 @@ const Dashboard = () => { return (
-

Dashboard

-

Overview of your UAMILS system

+

{t('dashboard.title')}

+

{t('dashboard.description')}

{/* Stats Grid */} diff --git a/management/src/pages/Tenants.jsx b/management/src/pages/Tenants.jsx index 554ad29..565ac18 100644 --- a/management/src/pages/Tenants.jsx +++ b/management/src/pages/Tenants.jsx @@ -3,6 +3,7 @@ import { useNavigate } from 'react-router-dom' import api from '../services/api' import toast from 'react-hot-toast' import TenantModal from '../components/TenantModal' +import { t } from '../utils/tempTranslations' // Temporary translation system import { PlusIcon, PencilIcon, @@ -82,16 +83,16 @@ const Tenants = () => { } const deleteTenant = async (tenantId) => { - if (!confirm('Are you sure you want to delete this tenant? This action cannot be undone.')) { + if (!confirm(t('tenants.confirmDelete'))) { return } try { await api.delete(`/management/tenants/${tenantId}`) - toast.success('Tenant deleted successfully') + toast.success(t('tenants.deleteSuccess')) loadTenants() } catch (error) { - toast.error('Failed to delete tenant') + toast.error(t('tenants.deleteError')) console.error('Error deleting tenant:', error) } } @@ -99,8 +100,8 @@ const Tenants = () => { const toggleTenantStatus = async (tenant) => { const action = tenant.is_active ? 'deactivate' : 'activate' const confirmMessage = tenant.is_active - ? `Are you sure you want to deactivate "${tenant.name}"? Users will not be able to access this tenant.` - : `Are you sure you want to activate "${tenant.name}"?` + ? t('tenants.confirmDeactivate', { name: tenant.name }) + : t('tenants.confirmActivate', { name: tenant.name }) if (!confirm(confirmMessage)) { return @@ -108,10 +109,10 @@ const Tenants = () => { try { await api.post(`/management/tenants/${tenant.id}/${action}`) - toast.success(`Tenant ${action}d successfully`) + toast.success(t(`tenants.${action}Success`)) loadTenants() } catch (error) { - toast.error(`Failed to ${action} tenant`) + toast.error(t(`tenants.${action}Error`)) console.error(`Error ${action}ing tenant:`, error) } } @@ -166,7 +167,7 @@ const Tenants = () => { ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800' }`}> - {isActive ? 'Active' : 'Inactive'} + {isActive ? t('common.active') : t('common.inactive')} ) } @@ -185,15 +186,15 @@ const Tenants = () => {
-

Tenants

-

Manage organizations and their configurations

+

{t('tenants.title')}

+

{t('tenants.description')}

@@ -204,7 +205,7 @@ const Tenants = () => { { - Tenant + {t('tenants.tenant')} - Domain + {t('tenants.domain')} - Auth Provider + {t('tenants.authProvider')} - Subscription + {t('tenants.subscription')} - Users + {t('tenants.users')} - Created + {t('tenants.created')} - Status + {t('tenants.status')} - Actions + {t('tenants.actions')} @@ -295,14 +296,14 @@ const Tenants = () => { @@ -322,24 +323,24 @@ const Tenants = () => { disabled={pagination.offset === 0} className="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 disabled:opacity-50" > - Previous + {t('common.previous')}

- Showing {pagination.offset + 1} to{' '} - - {Math.min(pagination.offset + pagination.limit, pagination.total)} - {' '} - of {pagination.total} results + {t('common.showingResults', { + start: pagination.offset + 1, + end: Math.min(pagination.offset + pagination.limit, pagination.total), + total: pagination.total + })}

@@ -349,15 +350,15 @@ const Tenants = () => { {tenants.length === 0 && !loading && (
-

No tenants

-

Get started by creating a new tenant.

+

{t('tenants.noTenants')}

+

{t('tenants.noTenantsDescription')}

diff --git a/management/src/utils/tempTranslations.js b/management/src/utils/tempTranslations.js new file mode 100644 index 0000000..663945e --- /dev/null +++ b/management/src/utils/tempTranslations.js @@ -0,0 +1,279 @@ +// Temporary translation system for management portal until Docker rebuild +const translations = { + en: { + nav: { + dashboard: 'Dashboard', + tenants: 'Tenants', + users: 'Users', + system: 'System' + }, + navigation: { + dashboard: 'Dashboard', + tenants: 'Tenants', + users: 'Users', + system: 'System', + logout: 'Logout' + }, + app: { + title: 'UAM-ILS Management Portal' + }, + tenants: { + title: 'Tenants', + description: 'Manage organizations and their configurations', + noTenants: 'No tenants', + noTenantsDescription: 'Get started by creating a new tenant.', + loadingTenants: 'Loading tenants...', + addTenant: 'Create Tenant', + createTenant: 'Create Tenant', + editTenant: 'Edit Tenant', + deleteTenant: 'Delete Tenant', + searchPlaceholder: 'Search tenants...', + tenant: 'Tenant', + tenantName: 'Tenant Name', + tenantSlug: 'Tenant Slug', + domain: 'Domain', + authProvider: 'Auth Provider', + subscription: 'Subscription', + users: 'Users', + status: 'Status', + created: 'Created', + lastActivity: 'Last Activity', + actions: 'Actions', + active: 'Active', + inactive: 'Inactive', + suspended: 'Suspended', + edit: 'Edit', + delete: 'Delete', + viewUsers: 'View Users', + confirmDelete: 'Are you sure you want to delete this tenant? This action cannot be undone.', + confirmActivate: 'Are you sure you want to activate "{{name}}"?', + confirmDeactivate: 'Are you sure you want to deactivate "{{name}}"? Users will not be able to access this tenant.', + deleteSuccess: 'Tenant deleted successfully', + deleteError: 'Failed to delete tenant', + activateSuccess: 'Tenant activated successfully', + activateError: 'Failed to activate tenant', + deactivateSuccess: 'Tenant deactivated successfully', + deactivateError: 'Failed to deactivate tenant', + deleteWarning: 'This action cannot be undone and will remove all associated data.', + totalTenants: 'Total Tenants', + activeTenants: 'Active Tenants' + }, + users: { + title: 'User Management', + noUsers: 'No users found', + addUser: 'Add User', + editUser: 'Edit User', + deleteUser: 'Delete User', + username: 'Username', + email: 'Email', + role: 'Role', + tenant: 'Tenant', + status: 'Status', + lastLogin: 'Last Login', + created: 'Created', + actions: 'Actions' + }, + dashboard: { + title: 'Dashboard', + description: 'Overview of your UAMILS system', + totalTenants: 'Total Tenants', + activeTenants: 'Active Tenants', + totalUsers: 'Total Users', + activeSessions: 'Active Sessions', + systemHealth: 'System Health', + good: 'Good', + issues: 'Issues' + }, + system: { + title: 'System Information', + serverInfo: 'Server Information', + databaseInfo: 'Database Information', + version: 'Version', + uptime: 'Uptime', + platform: 'Platform' + }, + common: { + loading: 'Loading...', + error: 'Error', + success: 'Success', + cancel: 'Cancel', + save: 'Save', + delete: 'Delete', + edit: 'Edit', + add: 'Add', + search: 'Search', + filter: 'Filter', + refresh: 'Refresh', + previous: 'Previous', + next: 'Next', + active: 'Active', + inactive: 'Inactive', + showingResults: 'Showing {{start}} to {{end}} of {{total}} results', + yes: 'Yes', + no: 'No', + ok: 'OK', + close: 'Close' + }, + auth: { + login: 'Login', + username: 'Username', + password: 'Password', + loginButton: 'Sign In', + logout: 'Logout' + } + }, + sv: { + nav: { + dashboard: 'Översikt', + tenants: 'Hyresgäster', + users: 'Användare', + system: 'System' + }, + navigation: { + dashboard: 'Översikt', + tenants: 'Hyresgäster', + users: 'Användare', + system: 'System', + logout: 'Logga ut' + }, + app: { + title: 'UAM-ILS Förvaltningsportal' + }, + tenants: { + title: 'Hyresgäster', + description: 'Hantera organisationer och deras konfigurationer', + noTenants: 'Inga hyresgäster', + noTenantsDescription: 'Kom igång genom att skapa en ny hyresgäst.', + loadingTenants: 'Laddar hyresgäster...', + addTenant: 'Skapa hyresgäst', + createTenant: 'Skapa hyresgäst', + editTenant: 'Redigera hyresgäst', + deleteTenant: 'Ta bort hyresgäst', + searchPlaceholder: 'Sök hyresgäster...', + tenant: 'Hyresgäst', + tenantName: 'Hyresgästnamn', + tenantSlug: 'Hyresgästslug', + domain: 'Domän', + authProvider: 'Auth-leverantör', + subscription: 'Prenumeration', + users: 'Användare', + status: 'Status', + created: 'Skapad', + lastActivity: 'Senaste aktivitet', + actions: 'Åtgärder', + active: 'Aktiv', + inactive: 'Inaktiv', + suspended: 'Avstängd', + edit: 'Redigera', + delete: 'Ta bort', + viewUsers: 'Visa användare', + confirmDelete: 'Är du säker på att du vill ta bort denna hyresgäst? Denna åtgärd kan inte ångras.', + confirmActivate: 'Är du säker på att du vill aktivera "{{name}}"?', + confirmDeactivate: 'Är du säker på att du vill deaktivera "{{name}}"? Användare kommer inte att kunna komma åt denna hyresgäst.', + deleteSuccess: 'Hyresgäst borttagen framgångsrikt', + deleteError: 'Misslyckades att ta bort hyresgäst', + activateSuccess: 'Hyresgäst aktiverad framgångsrikt', + activateError: 'Misslyckades att aktivera hyresgäst', + deactivateSuccess: 'Hyresgäst deaktiverad framgångsrikt', + deactivateError: 'Misslyckades att deaktivera hyresgäst', + deleteWarning: 'Denna åtgärd kan inte ångras och kommer att ta bort all associerad data.', + totalTenants: 'Totala hyresgäster', + activeTenants: 'Aktiva hyresgäster' + }, + users: { + title: 'Användarhantering', + noUsers: 'Inga användare hittades', + addUser: 'Lägg till användare', + editUser: 'Redigera användare', + deleteUser: 'Ta bort användare', + username: 'Användarnamn', + email: 'E-post', + role: 'Roll', + tenant: 'Hyresgäst', + status: 'Status', + lastLogin: 'Senaste inloggning', + created: 'Skapad', + actions: 'Åtgärder' + }, + dashboard: { + title: 'Instrumentpanel', + description: 'Översikt av ditt UAMILS-system', + totalTenants: 'Totala hyresgäster', + activeTenants: 'Aktiva hyresgäster', + totalUsers: 'Totala användare', + activeSessions: 'Aktiva sessioner', + systemHealth: 'Systemhälsa', + good: 'Bra', + issues: 'Problem' + }, + system: { + title: 'Systeminformation', + serverInfo: 'Serverinformation', + databaseInfo: 'Databasinformation', + version: 'Version', + uptime: 'Drifttid', + platform: 'Plattform' + }, + common: { + loading: 'Laddar...', + error: 'Fel', + success: 'Framgång', + cancel: 'Avbryt', + save: 'Spara', + delete: 'Ta bort', + edit: 'Redigera', + add: 'Lägg till', + search: 'Sök', + filter: 'Filtrera', + refresh: 'Uppdatera', + previous: 'Föregående', + next: 'Nästa', + active: 'Aktiv', + inactive: 'Inaktiv', + showingResults: 'Visar {{start}} till {{end}} av {{total}} resultat', + yes: 'Ja', + no: 'Nej', + ok: 'OK', + close: 'Stäng' + }, + auth: { + login: 'Logga in', + username: 'Användarnamn', + password: 'Lösenord', + loginButton: 'Logga in', + logout: 'Logga ut' + } + } +}; + +let currentLanguage = localStorage.getItem('language') || 'en'; + +export const t = (key, params = {}) => { + const keys = key.split('.'); + let value = translations[currentLanguage]; + + for (const k of keys) { + value = value?.[k]; + } + + let result = value || key; + + // Simple parameter interpolation + if (params && typeof params === 'object') { + Object.keys(params).forEach(param => { + const placeholder = `{{${param}}}`; + result = result.replace(new RegExp(placeholder, 'g'), params[param]); + }); + } + + return result; +}; + +export const changeLanguage = (lang) => { + currentLanguage = lang; + localStorage.setItem('language', lang); + // Trigger a page refresh to update all components + window.location.reload(); +}; + +export const getCurrentLanguage = () => currentLanguage; \ No newline at end of file