feat(localization): update project list translations and add new keys

- Enhanced localization JSON files for multiple languages, including Albanian, German, English, Spanish, Portuguese, and Chinese.
- Updated existing translation keys for consistency and clarity, particularly for task progress, archive confirmations, and filtering instructions.
- Introduced new keys for improved user experience, such as "yes", "no", "list", "group", and "noPermission".
- Ensured all translations align with the latest UI changes for better internationalization support.
This commit is contained in:
chamiakJ
2025-07-10 14:16:51 +05:30
parent bcfa18b1e8
commit f846230d59
9 changed files with 69 additions and 286 deletions

View File

@@ -3,21 +3,32 @@
"client": "Klienti", "client": "Klienti",
"category": "Kategoria", "category": "Kategoria",
"status": "Statusi", "status": "Statusi",
"tasksProgress": "Progresi i Detyrave", "tasksProgress": "Përparimi i Detyrave",
"updated_at": "Përditësuar Së Fundi", "updated_at": "E Përditësuar së Fundi",
"members": "Anëtarët", "members": "Anëtarët",
"setting": "Cilësimet", "setting": "Cilësimet",
"projects": "Projektet", "projects": "Projektet",
"refreshProjects": "Rifresko projektet", "refreshProjects": "Rifresko projektet",
"all": "Të Gjitha", "all": "Të gjitha",
"favorites": "Të Preferuarat", "favorites": "Të preferuarit",
"archived": "Të Arkivuara", "archived": "E arkivuar",
"placeholder": "Kërko sipas emrit", "placeholder": "Kërko sipas emrit",
"archive": "Arkivo", "archive": "Arkivo",
"unarchive": 'arkivo", "unarchive": "Çarkivo",
"archiveConfirm": "Jeni i sigurt që doni ta arkivoni këtë projekt?", "archiveConfirm": "Jeni i sigurt që dëshironi të arkivoni këtë projekt?",
"unarchiveConfirm": "Jeni i sigurt që doni ta çarkivoni këtë projekt?", "unarchiveConfirm": "Jeni i sigurt që dëshironi të çarkivoni këtë projekt?",
"clickToFilter": "Klikoni për të filtruar sipas", "yes": "Po",
"no": "Jo",
"clickToFilter": "Kliko për të filtruar sipas",
"noProjects": "Nuk u gjetën projekte", "noProjects": "Nuk u gjetën projekte",
"addToFavourites": "Shto të preferuarat" "addToFavourites": "Shto te të preferuarit",
"list": "Lista",
"group": "Grupi",
"listView": "Pamja e Listës",
"groupView": "Pamja e Grupit",
"groupBy": {
"category": "Kategoria",
"client": "Klienti"
},
"noPermission": "Nuk keni leje për të kryer këtë veprim"
} }

View File

@@ -17,7 +17,18 @@
"unarchive": "Dearchivieren", "unarchive": "Dearchivieren",
"archiveConfirm": "Sind Sie sicher, dass Sie dieses Projekt archivieren möchten?", "archiveConfirm": "Sind Sie sicher, dass Sie dieses Projekt archivieren möchten?",
"unarchiveConfirm": "Sind Sie sicher, dass Sie dieses Projekt dearchivieren möchten?", "unarchiveConfirm": "Sind Sie sicher, dass Sie dieses Projekt dearchivieren möchten?",
"yes": "Ja",
"no": "Nein",
"clickToFilter": "Zum Filtern klicken nach", "clickToFilter": "Zum Filtern klicken nach",
"noProjects": "Keine Projekte gefunden", "noProjects": "Keine Projekte gefunden",
"addToFavourites": "Zu Favoriten hinzufügen" "addToFavourites": "Zu Favoriten hinzufügen",
"list": "Liste",
"group": "Gruppe",
"listView": "Listenansicht",
"groupView": "Gruppenansicht",
"groupBy": {
"category": "Kategorie",
"client": "Kunde"
},
"noPermission": "Sie haben keine Berechtigung, diese Aktion durchzuführen"
} }

View File

@@ -17,6 +17,8 @@
"unarchive": "Unarchive", "unarchive": "Unarchive",
"archiveConfirm": "Are you sure you want to archive this project?", "archiveConfirm": "Are you sure you want to archive this project?",
"unarchiveConfirm": "Are you sure you want to unarchive this project?", "unarchiveConfirm": "Are you sure you want to unarchive this project?",
"yes": "Yes",
"no": "No",
"clickToFilter": "Click to filter by", "clickToFilter": "Click to filter by",
"noProjects": "No projects found", "noProjects": "No projects found",
"addToFavourites": "Add to favourites", "addToFavourites": "Add to favourites",
@@ -27,5 +29,6 @@
"groupBy": { "groupBy": {
"category": "Category", "category": "Category",
"client": "Client" "client": "Client"
} },
"noPermission": "You don't have permission to perform this action"
} }

View File

@@ -3,23 +3,25 @@
"client": "Cliente", "client": "Cliente",
"category": "Categoría", "category": "Categoría",
"status": "Estado", "status": "Estado",
"tasksProgress": "Progreso de tareas", "tasksProgress": "Progreso de Tareas",
"updated_at": "Última actualización", "updated_at": "Última Actualización",
"members": "Miembros", "members": "Miembros",
"setting": "Configuración", "setting": "Configuración",
"archive": "Archivar",
"projects": "Proyectos", "projects": "Proyectos",
"refreshProjects": "Actualizar proyectos", "refreshProjects": "Actualizar proyectos",
"all": "Todos", "all": "Todos",
"favorites": "Favoritos", "favorites": "Favoritos",
"archived": "Archivados", "archived": "Archivados",
"placeholder": "Buscar por nombre", "placeholder": "Buscar por nombre",
"archive": "Archivar",
"unarchive": "Desarchivar", "unarchive": "Desarchivar",
"archiveConfirm": "¿Estás seguro de que deseas archivar este proyecto?", "archiveConfirm": "¿Está seguro de que desea archivar este proyecto?",
"unarchiveConfirm": "¿Estás seguro de que deseas desarchivar este proyecto?", "unarchiveConfirm": "¿Está seguro de que desea desarchivar este proyecto?",
"clickToFilter": "Clique para filtrar por", "yes": "Sí",
"no": "No",
"clickToFilter": "Haga clic para filtrar por",
"noProjects": "No se encontraron proyectos", "noProjects": "No se encontraron proyectos",
"addToFavourites": "Añadir a favoritos", "addToFavourites": "Agregar a favoritos",
"list": "Lista", "list": "Lista",
"group": "Grupo", "group": "Grupo",
"listView": "Vista de Lista", "listView": "Vista de Lista",
@@ -27,5 +29,6 @@
"groupBy": { "groupBy": {
"category": "Categoría", "category": "Categoría",
"client": "Cliente" "client": "Cliente"
} },
"noPermission": "No tienes permiso para realizar esta acción"
} }

View File

@@ -6,17 +6,19 @@
"tasksProgress": "Progresso das Tarefas", "tasksProgress": "Progresso das Tarefas",
"updated_at": "Última Atualização", "updated_at": "Última Atualização",
"members": "Membros", "members": "Membros",
"setting": "Configuração", "setting": "Configurações",
"archive": "Arquivar",
"projects": "Projetos", "projects": "Projetos",
"refreshProjects": "Atualizar projetos", "refreshProjects": "Atualizar projetos",
"all": "Todos", "all": "Todos",
"favorites": "Favoritos", "favorites": "Favoritos",
"archived": "Arquivados", "archived": "Arquivados",
"placeholder": "Pesquisar por nome", "placeholder": "Pesquisar por nome",
"archiveConfirm": "Tem certeza de que deseja arquivar este projeto?", "archive": "Arquivar",
"unarchive": "Desarquivar", "unarchive": "Desarquivar",
"archiveConfirm": "Tem certeza de que deseja arquivar este projeto?",
"unarchiveConfirm": "Tem certeza de que deseja desarquivar este projeto?", "unarchiveConfirm": "Tem certeza de que deseja desarquivar este projeto?",
"yes": "Sim",
"no": "Não",
"clickToFilter": "Clique para filtrar por", "clickToFilter": "Clique para filtrar por",
"noProjects": "Nenhum projeto encontrado", "noProjects": "Nenhum projeto encontrado",
"addToFavourites": "Adicionar aos favoritos", "addToFavourites": "Adicionar aos favoritos",
@@ -27,5 +29,6 @@
"groupBy": { "groupBy": {
"category": "Categoria", "category": "Categoria",
"client": "Cliente" "client": "Cliente"
} },
"noPermission": "Você não tem permissão para realizar esta ação"
} }

View File

@@ -17,7 +17,18 @@
"unarchive": "取消归档", "unarchive": "取消归档",
"archiveConfirm": "您确定要归档此项目吗?", "archiveConfirm": "您确定要归档此项目吗?",
"unarchiveConfirm": "您确定要取消归档此项目吗?", "unarchiveConfirm": "您确定要取消归档此项目吗?",
"clickToFilter": "点击以筛选", "yes": "",
"no": "否",
"clickToFilter": "点击筛选",
"noProjects": "未找到项目", "noProjects": "未找到项目",
"addToFavourites": "添加到收藏" "addToFavourites": "添加到收藏",
"list": "列表",
"group": "分组",
"listView": "列表视图",
"groupView": "分组视图",
"groupBy": {
"category": "类别",
"client": "客户"
},
"noPermission": "您没有权限执行此操作"
} }

View File

@@ -1,10 +1,10 @@
import { RouteObject } from 'react-router-dom'; import { RouteObject } from 'react-router-dom';
import { Suspense } from 'react'; import { Suspense } from 'react';
import AdminCenterLayout from '@/layouts/admin-center-layout';
import { adminCenterItems } from '@/pages/admin-center/admin-center-constants'; import { adminCenterItems } from '@/pages/admin-center/admin-center-constants';
import { Navigate } from 'react-router-dom'; import { Navigate } from 'react-router-dom';
import { useAuthService } from '@/hooks/useAuth'; import { useAuthService } from '@/hooks/useAuth';
import { SuspenseFallback } from '@/components/suspense-fallback/suspense-fallback'; import { SuspenseFallback } from '@/components/suspense-fallback/suspense-fallback';
import AdminCenterLayout from '@/layouts/AdminCenterLayout';
const AdminCenterGuard = ({ children }: { children: React.ReactNode }) => { const AdminCenterGuard = ({ children }: { children: React.ReactNode }) => {
const isOwnerOrAdmin = useAuthService().isOwnerOrAdmin(); const isOwnerOrAdmin = useAuthService().isOwnerOrAdmin();

View File

@@ -1,259 +0,0 @@
# Service Worker Implementation
This directory contains the service worker implementation for Worklenz, providing offline functionality, caching, and performance improvements.
## Files Overview
- **`sw.js`** (in `/public/`) - The main service worker file
- **`serviceWorkerRegistration.ts`** - Registration and management utilities
- **`ServiceWorkerStatus.tsx`** (in `/components/`) - React component for SW status
## Features
### 🔄 Caching Strategies
1. **Cache First** - Static assets (JS, CSS, images)
- Serves from cache first, falls back to network
- Perfect for unchanging resources
2. **Network First** - API requests
- Tries network first, falls back to cache
- Ensures fresh data when online
3. **Stale While Revalidate** - HTML pages
- Serves cached version immediately
- Updates cache in background
### 📱 PWA Features
- **Offline Support** - App works without internet
- **Installable** - Can be installed on devices
- **Background Sync** - Sync data when online (framework ready)
- **Push Notifications** - Real-time notifications (framework ready)
## Usage
### Basic Integration
The service worker is automatically registered in `App.tsx`:
```tsx
import { registerSW } from './utils/serviceWorkerRegistration';
useEffect(() => {
registerSW({
onSuccess: (registration) => {
console.log('SW registered successfully');
},
onUpdate: (registration) => {
// Show update notification to user
},
onOfflineReady: () => {
console.log('App ready for offline use');
}
});
}, []);
```
### Using the Hook
```tsx
import { useServiceWorker } from '../utils/serviceWorkerRegistration';
const MyComponent = () => {
const { isOffline, swManager, clearCache, forceUpdate } = useServiceWorker();
return (
<div>
<p>Status: {isOffline ? 'Offline' : 'Online'}</p>
<button onClick={clearCache}>Clear Cache</button>
<button onClick={forceUpdate}>Update App</button>
</div>
);
};
```
### Status Component
```tsx
import ServiceWorkerStatus from '../components/service-worker-status/ServiceWorkerStatus';
// Minimal offline indicator
<ServiceWorkerStatus minimal />
// Full status with controls
<ServiceWorkerStatus showControls />
```
## Configuration
### Cacheable Resources
Edit the patterns in `sw.js`:
```javascript
// API endpoints that can be cached
const CACHEABLE_API_PATTERNS = [
/\/api\/project-categories/,
/\/api\/task-statuses/,
// Add more patterns...
];
// Resources that should never be cached
const NEVER_CACHE_PATTERNS = [
/\/api\/auth\/login/,
/\/socket\.io/,
// Add more patterns...
];
```
### Cache Names
Update version to force cache refresh:
```javascript
const CACHE_VERSION = 'v1.0.1'; // Increment when deploying
```
## Development
### Testing Offline
1. Open DevTools → Application → Service Workers
2. Check "Offline" to simulate offline mode
3. Verify app still functions
### Debugging
```javascript
// Check service worker status
navigator.serviceWorker.ready.then(registration => {
console.log('SW ready:', registration);
});
// Check cache contents
caches.keys().then(names => {
console.log('Cache names:', names);
});
```
### Cache Management
```javascript
// Clear all caches
caches.keys().then(names =>
Promise.all(names.map(name => caches.delete(name)))
);
// Clear specific cache
caches.delete('worklenz-api-v1.0.0');
```
## Best Practices
### 1. Cache Strategy Selection
- **Static Assets**: Cache First (fast loading)
- **API Data**: Network First (fresh data)
- **User Content**: Network Only (always fresh)
- **App Shell**: Cache First (instant loading)
### 2. Cache Invalidation
- Increment `CACHE_VERSION` when deploying
- Use versioned URLs for assets
- Set appropriate cache headers
### 3. Offline UX
- Show offline indicators
- Queue actions for later sync
- Provide meaningful offline messages
- Cache critical user data
### 4. Performance
- Cache only necessary resources
- Set cache size limits
- Clean up old caches regularly
- Monitor cache usage
## Monitoring
### Storage Usage
```javascript
// Check storage quota
navigator.storage.estimate().then(estimate => {
console.log('Used:', estimate.usage);
console.log('Quota:', estimate.quota);
});
```
### Cache Hit Rate
Monitor in DevTools → Network:
- Look for "from ServiceWorker" requests
- Check cache effectiveness
## Troubleshooting
### Common Issues
1. **SW not updating**
- Hard refresh (Ctrl+Shift+R)
- Clear browser cache
- Check CACHE_VERSION
2. **Resources not caching**
- Verify URL patterns
- Check NEVER_CACHE_PATTERNS
- Ensure HTTPS in production
3. **Offline features not working**
- Verify SW registration
- Check browser support
- Test cache strategies
### Reset Service Worker
```javascript
// Unregister and reload
navigator.serviceWorker.getRegistrations().then(registrations => {
registrations.forEach(registration => registration.unregister());
window.location.reload();
});
```
## Browser Support
- ✅ Chrome 45+
- ✅ Firefox 44+
- ✅ Safari 11.1+
- ✅ Edge 17+
- ❌ Internet Explorer
## Future Enhancements
1. **Background Sync**
- Queue offline actions
- Sync when online
2. **Push Notifications**
- Task assignments
- Project updates
- Deadline reminders
3. **Advanced Caching**
- Intelligent prefetching
- ML-based cache eviction
- Compression
4. **Offline Analytics**
- Track offline usage
- Cache hit rates
- Performance metrics
---
*Last updated: January 2025*