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:
@@ -3,21 +3,32 @@
|
||||
"client": "Klienti",
|
||||
"category": "Kategoria",
|
||||
"status": "Statusi",
|
||||
"tasksProgress": "Progresi i Detyrave",
|
||||
"updated_at": "Përditësuar Së Fundi",
|
||||
"tasksProgress": "Përparimi i Detyrave",
|
||||
"updated_at": "E Përditësuar së Fundi",
|
||||
"members": "Anëtarët",
|
||||
"setting": "Cilësimet",
|
||||
"projects": "Projektet",
|
||||
"refreshProjects": "Rifresko projektet",
|
||||
"all": "Të Gjitha",
|
||||
"favorites": "Të Preferuarat",
|
||||
"archived": "Të Arkivuara",
|
||||
"all": "Të gjitha",
|
||||
"favorites": "Të preferuarit",
|
||||
"archived": "E arkivuar",
|
||||
"placeholder": "Kërko sipas emrit",
|
||||
"archive": "Arkivo",
|
||||
"unarchive": "Ç'arkivo",
|
||||
"archiveConfirm": "Jeni i sigurt që doni ta arkivoni këtë projekt?",
|
||||
"unarchiveConfirm": "Jeni i sigurt që doni ta çarkivoni këtë projekt?",
|
||||
"clickToFilter": "Klikoni për të filtruar sipas",
|
||||
"unarchive": "Çarkivo",
|
||||
"archiveConfirm": "Jeni i sigurt që dëshironi të arkivoni këtë projekt?",
|
||||
"unarchiveConfirm": "Jeni i sigurt që dëshironi të çarkivoni këtë projekt?",
|
||||
"yes": "Po",
|
||||
"no": "Jo",
|
||||
"clickToFilter": "Kliko për të filtruar sipas",
|
||||
"noProjects": "Nuk u gjetën projekte",
|
||||
"addToFavourites": "Shto në 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"
|
||||
}
|
||||
|
||||
@@ -17,7 +17,18 @@
|
||||
"unarchive": "Dearchivieren",
|
||||
"archiveConfirm": "Sind Sie sicher, dass Sie dieses Projekt archivieren möchten?",
|
||||
"unarchiveConfirm": "Sind Sie sicher, dass Sie dieses Projekt dearchivieren möchten?",
|
||||
"yes": "Ja",
|
||||
"no": "Nein",
|
||||
"clickToFilter": "Zum Filtern klicken nach",
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
"unarchive": "Unarchive",
|
||||
"archiveConfirm": "Are you sure you want to archive this project?",
|
||||
"unarchiveConfirm": "Are you sure you want to unarchive this project?",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"clickToFilter": "Click to filter by",
|
||||
"noProjects": "No projects found",
|
||||
"addToFavourites": "Add to favourites",
|
||||
@@ -27,5 +29,6 @@
|
||||
"groupBy": {
|
||||
"category": "Category",
|
||||
"client": "Client"
|
||||
}
|
||||
},
|
||||
"noPermission": "You don't have permission to perform this action"
|
||||
}
|
||||
|
||||
@@ -3,23 +3,25 @@
|
||||
"client": "Cliente",
|
||||
"category": "Categoría",
|
||||
"status": "Estado",
|
||||
"tasksProgress": "Progreso de tareas",
|
||||
"updated_at": "Última actualización",
|
||||
"tasksProgress": "Progreso de Tareas",
|
||||
"updated_at": "Última Actualización",
|
||||
"members": "Miembros",
|
||||
"setting": "Configuración",
|
||||
"archive": "Archivar",
|
||||
"projects": "Proyectos",
|
||||
"refreshProjects": "Actualizar proyectos",
|
||||
"all": "Todos",
|
||||
"favorites": "Favoritos",
|
||||
"archived": "Archivados",
|
||||
"placeholder": "Buscar por nombre",
|
||||
"archive": "Archivar",
|
||||
"unarchive": "Desarchivar",
|
||||
"archiveConfirm": "¿Estás seguro de que deseas archivar este proyecto?",
|
||||
"unarchiveConfirm": "¿Estás seguro de que deseas desarchivar este proyecto?",
|
||||
"clickToFilter": "Clique para filtrar por",
|
||||
"archiveConfirm": "¿Está seguro de que desea archivar este proyecto?",
|
||||
"unarchiveConfirm": "¿Está seguro de que desea desarchivar este proyecto?",
|
||||
"yes": "Sí",
|
||||
"no": "No",
|
||||
"clickToFilter": "Haga clic para filtrar por",
|
||||
"noProjects": "No se encontraron proyectos",
|
||||
"addToFavourites": "Añadir a favoritos",
|
||||
"addToFavourites": "Agregar a favoritos",
|
||||
"list": "Lista",
|
||||
"group": "Grupo",
|
||||
"listView": "Vista de Lista",
|
||||
@@ -27,5 +29,6 @@
|
||||
"groupBy": {
|
||||
"category": "Categoría",
|
||||
"client": "Cliente"
|
||||
}
|
||||
},
|
||||
"noPermission": "No tienes permiso para realizar esta acción"
|
||||
}
|
||||
|
||||
@@ -6,17 +6,19 @@
|
||||
"tasksProgress": "Progresso das Tarefas",
|
||||
"updated_at": "Última Atualização",
|
||||
"members": "Membros",
|
||||
"setting": "Configuração",
|
||||
"archive": "Arquivar",
|
||||
"setting": "Configurações",
|
||||
"projects": "Projetos",
|
||||
"refreshProjects": "Atualizar projetos",
|
||||
"all": "Todos",
|
||||
"favorites": "Favoritos",
|
||||
"archived": "Arquivados",
|
||||
"placeholder": "Pesquisar por nome",
|
||||
"archiveConfirm": "Tem certeza de que deseja arquivar este projeto?",
|
||||
"archive": "Arquivar",
|
||||
"unarchive": "Desarquivar",
|
||||
"archiveConfirm": "Tem certeza de que deseja arquivar este projeto?",
|
||||
"unarchiveConfirm": "Tem certeza de que deseja desarquivar este projeto?",
|
||||
"yes": "Sim",
|
||||
"no": "Não",
|
||||
"clickToFilter": "Clique para filtrar por",
|
||||
"noProjects": "Nenhum projeto encontrado",
|
||||
"addToFavourites": "Adicionar aos favoritos",
|
||||
@@ -27,5 +29,6 @@
|
||||
"groupBy": {
|
||||
"category": "Categoria",
|
||||
"client": "Cliente"
|
||||
}
|
||||
},
|
||||
"noPermission": "Você não tem permissão para realizar esta ação"
|
||||
}
|
||||
|
||||
@@ -17,7 +17,18 @@
|
||||
"unarchive": "取消归档",
|
||||
"archiveConfirm": "您确定要归档此项目吗?",
|
||||
"unarchiveConfirm": "您确定要取消归档此项目吗?",
|
||||
"clickToFilter": "点击以筛选",
|
||||
"yes": "是",
|
||||
"no": "否",
|
||||
"clickToFilter": "点击筛选",
|
||||
"noProjects": "未找到项目",
|
||||
"addToFavourites": "添加到收藏"
|
||||
"addToFavourites": "添加到收藏",
|
||||
"list": "列表",
|
||||
"group": "分组",
|
||||
"listView": "列表视图",
|
||||
"groupView": "分组视图",
|
||||
"groupBy": {
|
||||
"category": "类别",
|
||||
"client": "客户"
|
||||
},
|
||||
"noPermission": "您没有权限执行此操作"
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import { RouteObject } from 'react-router-dom';
|
||||
import { Suspense } from 'react';
|
||||
import AdminCenterLayout from '@/layouts/admin-center-layout';
|
||||
import { adminCenterItems } from '@/pages/admin-center/admin-center-constants';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
import { useAuthService } from '@/hooks/useAuth';
|
||||
import { SuspenseFallback } from '@/components/suspense-fallback/suspense-fallback';
|
||||
import AdminCenterLayout from '@/layouts/AdminCenterLayout';
|
||||
|
||||
const AdminCenterGuard = ({ children }: { children: React.ReactNode }) => {
|
||||
const isOwnerOrAdmin = useAuthService().isOwnerOrAdmin();
|
||||
|
||||
@@ -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*
|
||||
Reference in New Issue
Block a user