Files
service-finder/docs/i18n_admin_audit_and_restructure_proposal.md
2026-07-01 02:27:38 +00:00

15 KiB

🌐 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)
  • garagesgarages.details, garages.analytics, garages.employees, garages.fleet (~180 kulcs)
  • gamificationgamification.badges, .competitions, .config, .dashboard, .leaderboard, .ledger, .levels, .params, .point_rules, .seasons, .users, .user_detail (~410 kulcs)
  • providers (~85 kulcs)
  • usersusers.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:

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):

{
  "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:

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):

<!-- 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:

<!-- Ú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:

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