admin_szolgáltatók_
This commit is contained in:
376
docs/i18n_admin_audit_and_restructure_proposal.md
Normal file
376
docs/i18n_admin_audit_and_restructure_proposal.md
Normal file
@@ -0,0 +1,376 @@
|
||||
# 🌐 Admin i18n Audit & Újrastrukturálási Javaslat
|
||||
|
||||
**Dátum:** 2026-06-30
|
||||
**Készítette:** Rendszer-Architect
|
||||
**Verzió:** 1.0
|
||||
**Cél:** Admin felület nyelvi moduljainak teljes körű felmérése, központi nyelvi állomány kialakítása, oldalakra bontási terv, többnyelvű (dropdown) nyelvválasztó bevezetése
|
||||
|
||||
---
|
||||
|
||||
## 1. Jelenlegi Helyzet (As-Is)
|
||||
|
||||
### 1.1 Három teljesen elkülönülő i18n rendszer
|
||||
|
||||
| Rendszer | Hely | Formátum | Fájlok | Össz. kulcs | Nyelvek |
|
||||
|----------|------|----------|--------|-------------|---------|
|
||||
| **Backend** | `backend/static/locales/` | Nested JSON (UPPER_SNAKE) | 2 db | ~130 sor/fájl | hu, en |
|
||||
| **Frontend Admin** | `frontend_admin/i18n/locales/` | Nested JSON (camelCase) | 2 db | ~800-900 sor/fájl | hu, en |
|
||||
| **Frontend Old (src)** | `frontend/src/i18n/` (korábbi) | TS objektum | 6 db | ~1600 sor/fájl | hu, en, de, ro, cz, sk |
|
||||
|
||||
> **⚠️ A backend és a frontend rendszerek teljesen függetlenek.** Más kulcs-sémát használnak (dot-notation vs UPPER_SNAKE_CASE), így közöttük NINCS kulcs-megosztás.
|
||||
|
||||
### 1.2 Frontend Admin jelenlegi struktúrája
|
||||
|
||||
```
|
||||
frontend_admin/i18n/locales/
|
||||
├── en.json (902 sor / ~700 kulcs)
|
||||
└── hu.json (804 sor / ~650 kulcs)
|
||||
```
|
||||
|
||||
Gyökér-szekciók a JSON-ben:
|
||||
- `permissions` (~29 kulcs)
|
||||
- `packages` (~67 kulcs)
|
||||
- `garages` → `garages.details`, `garages.analytics`, `garages.employees`, `garages.fleet` (~180 kulcs)
|
||||
- `gamification` → `gamification.badges`, `.competitions`, `.config`, `.dashboard`, `.leaderboard`, `.ledger`, `.levels`, `.params`, `.point_rules`, `.seasons`, `.users`, `.user_detail` (~410 kulcs)
|
||||
- `providers` (~85 kulcs)
|
||||
- `users` → `users.details` (~98 kulcs)
|
||||
|
||||
### 1.3 Admin oldalak leképezése (Pages ↔ i18n szekciók)
|
||||
|
||||
| Oldal (Vue fájl) | i18n Szekció | Kulcsszám |
|
||||
|-----------------|-------------|-----------|
|
||||
| `/` (index.vue) | — | — (dashboard nincs lefordítva) |
|
||||
| `/permissions/` | `permissions.*` | ~29 |
|
||||
| `/packages/` | `packages.*` | ~67 |
|
||||
| `/garages/` + `garages/[id]/` | `garages.*`, `garages.details.*`, `garages.analytics.*`, `garages.employees.*`, `garages.fleet.*` | ~180 |
|
||||
| `/gamification/` (index) | `gamification.dashboard.*` | ~25 |
|
||||
| `/gamification/badges` | `gamification.badges.*` | ~35 |
|
||||
| `/gamification/competitions` | `gamification.competitions.*` | ~40 |
|
||||
| `/gamification/config` | `gamification.config.*` | ~25 |
|
||||
| `/gamification/leaderboard` | `gamification.leaderboard.*` | ~40 |
|
||||
| `/gamification/ledger` | `gamification.ledger.*` | ~30 |
|
||||
| `/gamification/levels` | `gamification.levels.*` | ~35 |
|
||||
| `/gamification/params` | `gamification.params.*` | ~25 |
|
||||
| `/gamification/point-rules` | `gamification.point_rules.*` | ~40 |
|
||||
| `/gamification/seasons` | `gamification.seasons.*` | ~30 |
|
||||
| `/gamification/users/` + `[id]` | `gamification.users.*`, `gamification.user_detail.*` | ~40+50 |
|
||||
| `/providers/` + `[id]` | `providers.*` | ~85 |
|
||||
| `/users/` + `[id]` | `users.*`, `users.details.*` | ~98 |
|
||||
|
||||
---
|
||||
|
||||
## 2. Feltárt Problémák
|
||||
|
||||
### 2.1 Hiányzó központi (common/global) nyelvi szekció
|
||||
|
||||
Jelenleg **NINCS** `common` vagy `global` szekció az admin i18n-ben. Minden általános UI művelet (Mentés, Mégse, Törlés, Szerkesztés, Betöltés, Hiba) szekciónként DUPLIKÁLVA van.
|
||||
|
||||
### 2.2 Masszív kulcs-duplikáció
|
||||
|
||||
A `docs/i18n_duplicate_key_analysis.md` által feltárt frontend duplikációk az adminban is jelen vannak. Példák a `frontend_admin` fájlokból:
|
||||
|
||||
| Kulcs (EN) | Előfordulások száma | HU fordítás |
|
||||
|-----------|-------------------|-------------|
|
||||
| `cancel` | **9+** (permissions, packages, garages.employees, gamification.badges, competitions, levels, params, point_rules, seasons, providers) | "Mégse" |
|
||||
| `save` | **10+** (permissions, packages.details, garages.*, gamification.*, providers, users.details) | "Mentés" |
|
||||
| `loading` | **15+** (minden CRUD szekció) | "Betöltés..." |
|
||||
| `error` | **10+** (minden CRUD szekció) | "Nem sikerült..." |
|
||||
| `retry` | **10+** | "Újra" / "Újrapróbálkozás" (két változat!) |
|
||||
| `edit` | **8+** | "Szerkesztés" |
|
||||
| `delete` | **6+** | "Törlés" |
|
||||
| `actions` | **6+** | "Műveletek" |
|
||||
| `no_items` / `no_results` | **8+** | "Nincs..." |
|
||||
| `status` | **6+** | "Státusz" |
|
||||
| `save_error` | **8+** | "Hiba történt..." |
|
||||
|
||||
### 2.3 HU oldalon inkonzisztens fordítások
|
||||
|
||||
- `retry`: hol "Újra" (`permissions.retry`, `packages.retry`), hol "Újrapróbálkozás" (`gamification.badges.retry`)
|
||||
- `cancel`: hol "Mégse" (többnyire), de van ahol nincs következetesen
|
||||
- `save_success` vs `updated` vs `created`: eltérő sablonok
|
||||
|
||||
### 2.4 Csak 2 nyelv támogatott az adminban
|
||||
|
||||
A `nuxt.config.ts` i18n beállításaiban csak `hu` és `en` szerepel:
|
||||
```typescript
|
||||
locales: [
|
||||
{ code: 'hu', iso: 'hu-HU', file: 'hu.json', name: 'Magyar' },
|
||||
{ code: 'en', iso: 'en-GB', file: 'en.json', name: 'English' },
|
||||
]
|
||||
```
|
||||
|
||||
A `frontend_old` LanguageSwitcher már 4 nyelvet támogat (hu, en, de, fr).
|
||||
Előző audit szerint a korábbi `frontend/src/i18n/` is tartalmazott részleges de, ro, cz, sk fordításokat.
|
||||
|
||||
### 2.5 Nyelvválasztó jelenleg kétállású kapcsoló
|
||||
|
||||
A `frontend_admin/layouts/default.vue` topbar-jában a nyelvválasztó **két gomb** (HU / EN), nem pedig egy legördülő menü. Ez nem skálázható 3+ nyelv esetén.
|
||||
|
||||
### 2.6 Backend i18n aszimmetria
|
||||
|
||||
- A `backend/static/locales/hu.json` (83 sor) és `en.json` (76 sor) között eltérés van a kulcsok számában (pl. `SENTINEL.APPROVAL.REQUIRED` EN: "Approval required", HU-ban hosszabb)
|
||||
- Backend hiányzik: német és más nyelvű backend fordítások
|
||||
|
||||
---
|
||||
|
||||
## 3. Javasolt Megoldás (To-Be)
|
||||
|
||||
### 3.1 Központi/globális nyelvi állomány (`common`)
|
||||
|
||||
**Létrehozandó:** új `common` gyökér-szekció mindkét fájlban
|
||||
|
||||
Tartalma (javasolt kulcsok):
|
||||
|
||||
```json
|
||||
{
|
||||
"common": {
|
||||
"save": "Mentés",
|
||||
"saving": "Mentés...",
|
||||
"cancel": "Mégse",
|
||||
"confirm": "Megerősítés",
|
||||
"discard": "Elvetés",
|
||||
"delete": "Törlés",
|
||||
"deleting": "Törlés...",
|
||||
"edit": "Szerkesztés",
|
||||
"create": "Létrehozás",
|
||||
"close": "Bezárás",
|
||||
"back": "Vissza",
|
||||
"next": "Következő",
|
||||
"previous": "Előző",
|
||||
"search": "Keresés",
|
||||
"filter": "Szűrés",
|
||||
"reset": "Visszaállítás",
|
||||
"clear": "Törlés",
|
||||
"retry": "Újra",
|
||||
"loading": "Betöltés...",
|
||||
"error": "Hiba",
|
||||
"success": "Siker",
|
||||
"no_results": "Nincs találat",
|
||||
"no_data": "Nincs adat",
|
||||
"yes": "Igen",
|
||||
"no": "Nem",
|
||||
"continue": "Tovább",
|
||||
"exit": "Kilépés",
|
||||
"save_changes": "Változtatások Mentése",
|
||||
"confirm_delete": "Biztosan törölni szeretnéd?",
|
||||
"unknown_error": "Ismeretlen hiba",
|
||||
"all": "Mind",
|
||||
"none": "Nincs",
|
||||
"optional": "opcionális",
|
||||
"required": "kötelező"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Használati elv:** A Vue komponensek elsődlegesen a `common.*` kulcsokat használják. Csak ha egy gombnak szekció-specifikus szövege van (pl. "Csomag törlése" ≠ általános "Törlés"), akkor kell szekció-specifikus kulcs.
|
||||
|
||||
### 3.2 Oldalakra bontás javaslata (lazy loading támogatás)
|
||||
|
||||
Jelenleg a `nuxt.config.ts`-ben `lazy: false` van beállítva, ami azt jelenti, hogy minden nyelvi fájl betöltődik induláskor. A javasolt struktúra lehetővé teszi a `lazy: true` váltást.
|
||||
|
||||
**Új fájl struktúra:**
|
||||
|
||||
```
|
||||
frontend_admin/i18n/
|
||||
├── locales/
|
||||
│ ├── common.en.json ← központi alapértékek (EN)
|
||||
│ ├── common.hu.json ← központi alapértékek (HU)
|
||||
│ ├── permissions.en.json
|
||||
│ ├── permissions.hu.json
|
||||
│ ├── packages.en.json
|
||||
│ ├── packages.hu.json
|
||||
│ ├── garages.en.json
|
||||
│ ├── garages.hu.json
|
||||
│ ├── providers.en.json
|
||||
│ ├── providers.hu.json
|
||||
│ ├── users.en.json
|
||||
│ ├── users.hu.json
|
||||
│ ├── gamification-dashboard.{en,hu}.json
|
||||
│ ├── gamification-badges.{en,hu}.json
|
||||
│ ├── gamification-competitions.{en,hu}.json
|
||||
│ ├── gamification-config.{en,hu}.json
|
||||
│ ├── gamification-leaderboard.{en,hu}.json
|
||||
│ ├── gamification-ledger.{en,hu}.json
|
||||
│ ├── gamification-levels.{en,hu}.json
|
||||
│ ├── gamification-params.{en,hu}.json
|
||||
│ ├── gamification-point-rules.{en,hu}.json
|
||||
│ ├── gamification-seasons.{en,hu}.json
|
||||
│ ├── gamification-users.{en,hu}.json
|
||||
│ └── gamification-user-detail.{en,hu}.json
|
||||
```
|
||||
|
||||
**`nuxt.config.ts` módosítása:**
|
||||
|
||||
```typescript
|
||||
i18n: {
|
||||
locales: [
|
||||
{ code: 'hu', iso: 'hu-HU', file: 'common.hu.json', name: 'Magyar' },
|
||||
{ code: 'en', iso: 'en-GB', file: 'common.en.json', name: 'English' },
|
||||
{ code: 'de', iso: 'de-DE', file: 'common.de.json', name: 'Deutsch' },
|
||||
],
|
||||
defaultLocale: 'hu',
|
||||
lazy: true,
|
||||
langDir: 'locales/',
|
||||
strategy: 'no_prefix',
|
||||
detectBrowserLanguage: {
|
||||
useCookie: true,
|
||||
cookieKey: 'i18n_redirected',
|
||||
redirectOn: 'root',
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 Többnyelvűség (3+ nyelv) bevezetése
|
||||
|
||||
**Új nyelv hozzáadásának lépései:**
|
||||
|
||||
1. Új fájl létrehozása: pl. `common.de.json`, `permissions.de.json`, stb.
|
||||
2. A nyelv felvétele a `nuxt.config.ts` `locales` tömbjébe
|
||||
3. Fordítások elkészítése (kezdetben csak `common` + a leggyakoribb admin oldalak)
|
||||
4. Backend oldalon: új `de.json` fájl a `backend/static/locales/` mappába
|
||||
5. A backend `i18n.py` automatikusan betölti, ha a fájl létezik
|
||||
|
||||
**Előkészített nyelvek (részleges fordítások megléte alapján):**
|
||||
- **Deutsch (de)** — volt már részleges fordítás a régi frontend-ben
|
||||
- **Français (fr)** — volt a LanguageSwitcher-ben
|
||||
- **Română (ro)** — volt részleges fordítás a régi frontend-ben
|
||||
- **Čeština (cz)** — volt részleges fordítás a régi frontend-ben
|
||||
- **Slovenčina (sk)** — volt részleges fordítás a régi frontend-ben
|
||||
|
||||
### 3.4 Nyelvválasztó legördülő menüvé alakítása
|
||||
|
||||
**Jelenlegi kód** (`frontend_admin/layouts/default.vue`, 158-170. sor):
|
||||
|
||||
```html
|
||||
<!-- JELENLEG: kétállású kapcsoló -->
|
||||
<div class="flex items-center bg-slate-700/50 rounded-lg p-0.5">
|
||||
<button v-for="locale in availableLocales" :key="locale.code"
|
||||
@click="switchLocale(locale.code)"
|
||||
class="px-2.5 py-1 text-xs font-medium rounded-md transition"
|
||||
:class="currentLocale === locale.code
|
||||
? 'bg-indigo-600 text-white shadow-sm'
|
||||
: 'text-slate-400 hover:text-white'"
|
||||
>
|
||||
{{ locale.code === 'hu' ? 'HU' : 'EN' }}
|
||||
</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
**Javasolt új kód:**
|
||||
|
||||
```html
|
||||
<!-- ÚJ: legördülő nyelvválasztó -->
|
||||
<div class="language-switcher relative">
|
||||
<button @click="langDropdownOpen = !langDropdownOpen"
|
||||
class="flex items-center gap-2 px-3 py-1.5 bg-slate-700/50 rounded-lg text-xs font-medium
|
||||
hover:bg-slate-600/50 transition border border-slate-600/50"
|
||||
>
|
||||
<span>{{ getFlagEmoji(currentLocale) }}</span>
|
||||
<span>{{ getCurrentLanguageLabel() }}</span>
|
||||
<svg class="w-3.5 h-3.5 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Dropdown -->
|
||||
<div v-if="langDropdownOpen"
|
||||
class="absolute right-0 mt-1 bg-slate-800 border border-slate-700 rounded-lg shadow-xl z-50 min-w-[140px]"
|
||||
>
|
||||
<button v-for="locale in availableLocales" :key="locale.code"
|
||||
@click="switchLocale(locale.code); langDropdownOpen = false"
|
||||
class="w-full text-left px-3 py-2 text-xs hover:bg-slate-700 flex items-center gap-2 transition"
|
||||
:class="{ 'text-indigo-400': locale.code === currentLocale }"
|
||||
>
|
||||
<span>{{ getFlagEmoji(locale.code) }}</span>
|
||||
<span>{{ locale.name }}</span>
|
||||
<span v-if="locale.code === currentLocale" class="ml-auto text-indigo-400">✓</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
**`script` kiegészítés:**
|
||||
|
||||
```typescript
|
||||
const langDropdownOpen = ref(false)
|
||||
|
||||
function getFlagEmoji(code: string): string {
|
||||
const flags: Record<string, string> = {
|
||||
hu: '🇭🇺', en: '🇬🇧', de: '🇩🇪', fr: '🇫🇷',
|
||||
ro: '🇷🇴', cz: '🇨🇿', sk: '🇸🇰',
|
||||
}
|
||||
return flags[code] || '🌐'
|
||||
}
|
||||
|
||||
function getCurrentLanguageLabel(): string {
|
||||
const lang = availableLocales.value.find(l => l.code === currentLocale.value)
|
||||
return lang?.name || currentLocale.value.toUpperCase()
|
||||
}
|
||||
```
|
||||
|
||||
### 3.5 Backend i18n kiegészítése
|
||||
|
||||
A backend `i18n.py` már támogatja az automatikus betöltést — bármely `.json` fájl a `backend/static/locales/` mappában automatikusan felkerül a cache-be. Új nyelv esetén csak a JSON fájlt kell létrehozni.
|
||||
|
||||
A `nuxt.config.ts`-ben a `PATCH /api/v1/auth/me/language` végpont már támogatja a nyelv perzisztálását a backend felé — ez működni fog új nyelvekkel is, mivel a `preferred_language` mező egy szabad string.
|
||||
|
||||
---
|
||||
|
||||
## 4. Ütemezés (Mérföldkövek)
|
||||
|
||||
### M1: Központi `common` szekció létrehozása
|
||||
- Új `common` szekció felvétele az `en.json` és `hu.json` fájlokba
|
||||
- A duplikált kulcsok (cancel, save, loading, stb.) eltávolítása a szekció-specifikus részekből
|
||||
- Vue komponensek átírása: `$t('common.cancel')` használata a szekció-specifikus helyett
|
||||
- **Érintett fájlok:** `frontend_admin/i18n/locales/*.json`, `frontend_admin/pages/*.vue`, `frontend_admin/layouts/default.vue`
|
||||
|
||||
### M2: Fájlok oldalakra bontása (lazy loading)
|
||||
- A monolit `en.json` és `hu.json` szétbontása oldal-specifikus fájlokra
|
||||
- `nuxt.config.ts` frissítése (`lazy: true`)
|
||||
- Tesztelés: minden oldal megfelelően betölti a saját nyelvi fájlját
|
||||
- **Érintett fájlok:** `frontend_admin/i18n/locales/*`, `frontend_admin/nuxt.config.ts`
|
||||
|
||||
### M3: Nyelvválasztó dropdown bevezetése
|
||||
- `default.vue` layoutban a kétállású HU/EN kapcsoló cseréje legördülő menüre
|
||||
- Flag emoji támogatás
|
||||
- Több nyelv (de, fr) felvétele a konfigurációba
|
||||
- **Érintett fájlok:** `frontend_admin/layouts/default.vue`, `frontend_admin/nuxt.config.ts`
|
||||
|
||||
### M4: Új nyelvek backend támogatása
|
||||
- `de.json`, `fr.json` létrehozása a `backend/static/locales/` mappában
|
||||
- Legalább a COMMON és AUTH szekciók lefordítása
|
||||
- **Érintett fájlok:** `backend/static/locales/*.json`
|
||||
|
||||
### M5: Backend i18n aszimmetria javítása
|
||||
- `hu.json` és `en.json` kulcs-szinkronizációja
|
||||
- Hiányzó kulcsok pótlása
|
||||
- **Érintett fájlok:** `backend/static/locales/*.json`
|
||||
|
||||
---
|
||||
|
||||
## 5. Kockázatok és Függőségek
|
||||
|
||||
| Kockázat | Hatás | Valószínűség | Mérséklés |
|
||||
|----------|-------|-------------|-----------|
|
||||
| Vue komponensekben elszórt `$t('szekcio.kulcs')` hívások eltörnek az átnevezés után | Magas | Közepes | Codebase search (`$t(`) minden hívásra, fokozatos átállás |
|
||||
| Lazy loading miatt inicializálási késleltetés | Alacsony | Alacsony | `common` fájl előtöltése |
|
||||
| Backend és frontend közötti nyelvi kód inkonzisztencia | Közepes | Alacsony | Mindkét oldalon azonos ISO kódok használata |
|
||||
| Új nyelv hozzáadásánál a teljes admin felület nem lesz lefordítva | Közepes | Magas | Részleges fordítási státusz jelzése, angol fallback működik |
|
||||
|
||||
---
|
||||
|
||||
## 6. Összefoglaló
|
||||
|
||||
A jelenlegi admin i18n rendszer funkcionálisan működik, de strukturálisan optimalizálatlan:
|
||||
|
||||
1. **~50%-os kulcs-duplikáció** a `common` szekció hiánya miatt
|
||||
2. **Skálázhatatlan** - a monolit JSON fájlok 800+ sorosak, nehezen karbantarthatók
|
||||
3. **Csak 2 nyelv** - a régi frontend már 6 nyelvet ismert, az admin le van maradva
|
||||
4. **Kétállású kapcsoló** - nem bővíthető 3+ nyelvre
|
||||
|
||||
A javasolt restructuring:
|
||||
- Bevezeti a központi `common` szekciót (30+ általános kulcs)
|
||||
- Oldalakra bontja a monolit fájlokat (lazy loading)
|
||||
- Dropdown nyelvválasztóra cseréli a kapcsolót
|
||||
- Előkészíti a terepet 6+ nyelv támogatásához
|
||||
- Backend szinkronban marad a frontenddel
|
||||
Reference in New Issue
Block a user