Add i18n support with locales for button text
- Create locales directory with en.yml and hu.yml translation files - Update WelcomeBanner component to use i18n helper for button labels - Remove login_button_text and register_button_text from settings.yml - Update CLAUDE.md documentation with i18n architecture details - Button text now properly localized: hu (Belépés/Regisztráció) and en (Log in/Sign up)
This commit is contained in:
parent
c4f807356c
commit
aeb7950d14
5 changed files with 108 additions and 62 deletions
135
CLAUDE.md
135
CLAUDE.md
|
@ -10,55 +10,80 @@ Ez egy **Discourse fórum téma komponens** a Nyíltvilág magyar technológiai
|
|||
|
||||
### Komponens felépítés
|
||||
|
||||
A téma komponens három fő fájlból áll:
|
||||
A téma komponens a következő fő elemekből áll:
|
||||
|
||||
1. **index.html** - HTML sablon az üdvözlő bannerhez (statikus tartalom)
|
||||
2. **script.js** - Discourse API inicializáló, amely kezeli:
|
||||
- Az oldal láthatóságának váltását (csak a főoldalon jeleníti meg a bannert)
|
||||
- Az egyedi keresőmező renderelését és integrációját a Discourse SearchMenu-jével
|
||||
- Mobil detektálást és feltételes renderelést
|
||||
3. **style.css** - Reszponzív stílusok CSS változókkal
|
||||
1. **javascripts/discourse/components/welcome-banner.gjs** - Glimmer komponens a banner renderelésére
|
||||
- Felhasználói állapot kezelése (bejelentkezett/nem bejelentkezett)
|
||||
- Dinamikus tartalom megjelenítés
|
||||
- Keresési funkció integráció bejelentkezett felhasználóknak
|
||||
- Belépés/Regisztráció gombok nem bejelentkezett felhasználóknak
|
||||
2. **javascripts/discourse/api-initializers/welcome-banner.js** - Discourse API inicializáló
|
||||
- Plugin outlet integráció (below-header vagy above-content)
|
||||
3. **common/common.scss** - Reszponzív stílusok CSS változókkal
|
||||
4. **settings.yml** - Admin beállítások a banner testreszabásához
|
||||
5. **locales/** - i18n fordítások (en.yml, hu.yml)
|
||||
|
||||
### Kulcsfontosságú technikai minták
|
||||
|
||||
**Discourse Plugin API integráció**
|
||||
- Az `apiInitializer`-t használja a `discourse/lib/api`-ból (modern megközelítés)
|
||||
- Az `api.onPageChange()` hookra csatlakozik, hogy URL alapján mutassa/rejtse a bannert
|
||||
- Integrálódik a Discourse natív `SearchMenu` komponensével az `api.openSearchMenu()` segítségével
|
||||
**Glimmer Component alapú architektúra**
|
||||
- Modern `@glimmer/component` használata
|
||||
- Reactive getterek a dinamikus tartalom kezelésére (`heroTitle`, `heroContent`, `isAnonymous`)
|
||||
- `@service` injekció: `currentUser`, `router`, `site`
|
||||
- Template markup a `<template>` tagben (gjs fájl formátum)
|
||||
|
||||
**Felhasználói állapot kezelés**
|
||||
- `currentUser` service használata a bejelentkezési állapot ellenőrzésére
|
||||
- `isAnonymous` getter: `!this.currentUser` - meghatározza, hogy látogató vagy bejelentkezett felhasználó
|
||||
- Feltételes tartalom renderelés az állapot alapján
|
||||
|
||||
**i18n támogatás**
|
||||
- Fordítási fájlok a `locales/` mappában (en.yml, hu.yml)
|
||||
- `i18n` helper használata a template-ben a gombok lokalizálásához
|
||||
- Példa: `{{i18n "welcome_banner.buttons.login"}}` → "Belépés" (hu) vagy "Log in" (en)
|
||||
|
||||
**Keresési integráció mintája**
|
||||
Az egyedi keresőmező a hero szekcióban így működik:
|
||||
1. Egyedi input mező renderelése a `.search-container` konténerbe
|
||||
2. Fókuszáláskor/bevitelkor a Discourse natív SearchMenu megnyitása
|
||||
3. Értékek szinkronizálása az egyedi input és a natív `.search-menu input.search-query` között
|
||||
4. Űrlap beküldés delegálása a Discourse keresési űrlapjához
|
||||
- Discourse natív `SearchMenu` komponens integrációja bejelentkezett felhasználóknak
|
||||
- Mobil detektálás: `this.site.mobileView` - keresés csak asztali nézetben
|
||||
- Feltételes renderelés: `{{#if (and settings.enable_hero_search (not this.isMobile))}}`
|
||||
|
||||
**Idempotens renderelés**
|
||||
A `renderSearchInput()` függvény ellenőrzi, hogy a keresőmező már létezik-e, mielőtt létrehozná, így megakadályozza a duplikált elemeket, amikor az API többször is alkalmazza az inicializálót.
|
||||
**Navigációs integráció**
|
||||
- `DButton` komponens használata a belépés/regisztráció gombokhoz
|
||||
- Router service használata: `this.router.transitionTo("login")` és `"signup"`
|
||||
- Csak nem bejelentkezett felhasználóknak jelenik meg
|
||||
|
||||
**Mobil kezelés**
|
||||
A keresési funkció le van tiltva mobilon (az `isMobileView()` függvényen keresztül), hogy elkerülje az ütközéseket a Discourse mobil felületével.
|
||||
**Route alapú megjelenítés**
|
||||
- `displayForRoute` getter ellenőrzi az aktuális route-ot
|
||||
- Beállítás alapján: `homepage_only` vagy `all_pages`
|
||||
- Homepage route-ok: `discovery.latest`, `discovery.categories`
|
||||
|
||||
**Kód minőség és best practice-ek**
|
||||
- Következetes arrow function használat
|
||||
- Angol osztálynevek és kommentek a nemzetközi standardok szerint
|
||||
- Optimalizált renderelés egyetlen `requestAnimationFrame` hívással
|
||||
- Modern Glimmer/Ember konvenciók
|
||||
- Angol osztálynevek és kommentek
|
||||
- Accessibility támogatás (`role="search"`, `aria-label` attribútumok)
|
||||
- Lifecycle hook-ok: `didInsert`, `willDestroy`
|
||||
|
||||
## Fontos implementációs részletek
|
||||
|
||||
**Oldal láthatósági logika** (script.js:4-13)
|
||||
- A banner csak akkor jelenik meg, ha `url === "/"`
|
||||
- Minden más oldalon a banner rejtve van `display: none` segítségével
|
||||
**Felhasználói állapot alapú tartalom** (welcome-banner.gjs:38-52)
|
||||
- `isAnonymous` getter ellenőrzi a `currentUser` service-t
|
||||
- `heroTitle` és `heroContent` getterek dinamikusan választanak a settings között:
|
||||
- Bejelentkezett: `settings.hero_title_html` / `settings.hero_content_html`
|
||||
- Nem bejelentkezett: `settings.hero_title_anonymous_html` / `settings.hero_content_anonymous_html`
|
||||
|
||||
**Keresés szinkronizáció** (script.js:54-60)
|
||||
- Az egyedi input értéke szinkronizálva van a Discourse SearchMenu inputjával
|
||||
- A Discourse natív keresési funkcióját `input` esemény kiváltásával aktiválja
|
||||
- Egyesített event handler (`handleSearchInteraction`) a duplikált kód elkerülésére
|
||||
**Gombok vs keresés logika** (welcome-banner.gjs:84-102)
|
||||
- Nem bejelentkezett felhasználóknak: `.hero-buttons` div két DButton-nal
|
||||
- Bejelentkezett felhasználóknak: `.search-container` a SearchMenu komponenssel
|
||||
- Csak akkor jelenik meg, ha `settings.enable_hero_search` engedélyezett és nem mobil
|
||||
|
||||
**Optimalizált renderelés** (script.js:90-99)
|
||||
- Egyetlen `requestAnimationFrame` hívás a többszörös kísérlet helyett
|
||||
- Biztosítja, hogy az elem létezzen akkor is, ha a DOM nem teljesen készen áll
|
||||
**i18n fordítások** (locales/hu.yml, locales/en.yml)
|
||||
- Gomb szövegek: `welcome_banner.buttons.login` és `welcome_banner.buttons.register`
|
||||
- Magyar: "Belépés" / "Regisztráció"
|
||||
- Angol: "Log in" / "Sign up"
|
||||
|
||||
**Route detektálás** (welcome-banner.gjs:18-26)
|
||||
- `displayForRoute` getter ellenőrzi a `router.currentRouteName`-t
|
||||
- Homepage: `discovery.latest` vagy `discovery.categories`
|
||||
- Beállítás: `show_on_pages` (homepage_only / all_pages)
|
||||
|
||||
## CSS architektúra
|
||||
|
||||
|
@ -83,23 +108,41 @@ A keresési funkció le van tiltva mobilon (az `isMobileView()` függvényen ker
|
|||
## Fejlesztési megjegyzések
|
||||
|
||||
**Komponens tesztelése:**
|
||||
- A módosítások megtekintése a fórum főoldalára navigálva (/)
|
||||
- Módosítások megtekintése a fórum főoldalára navigálva (/)
|
||||
- Oldal láthatóság tesztelése más URL-ekre navigálva
|
||||
- Keresés tesztelése az egyedi keresőmezőbe való fókuszálással/gépelés (csak asztalon)
|
||||
- Bejelentkezett állapot tesztelése: keresés megjelenik
|
||||
- Nem bejelentkezett állapot tesztelése: belépés/regisztráció gombok megjelennek
|
||||
- Mobil nézet tesztelése: keresés eltűnik mobilon
|
||||
- i18n tesztelés: nyelv váltás a fórum beállításokban
|
||||
|
||||
**Gyakori módosítások:**
|
||||
- Üdvözlő szöveg frissítése: index.html 6-20. sor szerkesztése
|
||||
- CTA kártyák hozzáadása/eltávolítása: index.html 27-102. sor módosítása
|
||||
- Stílusok módosítása: style.css változók vagy szelektorok módosítása
|
||||
- Keresési viselkedés módosítása: script.js `renderSearchInput()` függvény (18-88. sor)
|
||||
- Hero szöveg frissítése: settings.yml `hero_title_html`, `hero_content_html`, `hero_title_anonymous_html`, `hero_content_anonymous_html`
|
||||
- Gomb szövegek módosítása: locales/hu.yml és locales/en.yml szerkesztése
|
||||
- CTA kártyák módosítása: settings.yml `cta_card_*` beállítások
|
||||
- Stílusok módosítása: common/common.scss változók vagy szelektorok
|
||||
- Komponens logika módosítása: javascripts/discourse/components/welcome-banner.gjs
|
||||
|
||||
**Osztálynevek konvenciói:**
|
||||
- `.search-container` - Fő kereső konténer
|
||||
- `.search-wrapper` - Keresőmező wrapper elem
|
||||
- `.search-input` - Keresőmező input elem
|
||||
- `.cta-*` - Call-To-Action kategória kártyák
|
||||
- `.hero-*` - Hero szekció elemei
|
||||
- `.welcome-card` - Fő banner konténer
|
||||
- `.hero-section` - Hero szekció konténer
|
||||
- `.hero-content` - Hero szöveges tartalom
|
||||
- `.hero-title` - Hero cím
|
||||
- `.hero-description` - Hero leírás
|
||||
- `.hero-buttons` - Belépés/Regisztráció gomb konténer (csak nem bejelentkezetteknek)
|
||||
- `.hero-login-btn` - Belépés gomb
|
||||
- `.hero-register-btn` - Regisztráció gomb
|
||||
- `.search-container` - Kereső konténer (csak bejelentkezetteknek)
|
||||
- `.cta-section` - CTA kártyák szekció
|
||||
- `.cta-card` - Egyedi CTA kártya
|
||||
- Angol osztálynevek következetesen használva
|
||||
|
||||
**Discourse API verzió:**
|
||||
Ez a komponens a modern `apiInitializer` mintát használja. Régebbi Discourse verziókkal való munka esetén szükség lehet a `withPluginApi` használatára helyette.
|
||||
**Discourse verzió kompatibilitás:**
|
||||
- Modern Glimmer komponens architektúra (Discourse 3.1+)
|
||||
- `apiInitializer` használata (Discourse 3.0+)
|
||||
- gjs fájl formátum támogatás szükséges
|
||||
|
||||
**i18n bővítés:**
|
||||
Új fordítások hozzáadása:
|
||||
1. Fordítási kulcs hozzáadása `locales/en.yml` és `locales/hu.yml` fájlokhoz
|
||||
2. `i18n` helper használata a template-ben: `{{i18n "welcome_banner.your.key"}}`
|
||||
3. További nyelvek hozzáadása: új `locales/[lang].yml` fájl létrehozása
|
||||
|
|
|
@ -9,6 +9,7 @@ import willDestroy from "@ember/render-modifiers/modifiers/will-destroy";
|
|||
import SearchMenu from "discourse/components/search-menu";
|
||||
import DButton from "discourse/components/d-button";
|
||||
import icon from "discourse-common/helpers/d-icon";
|
||||
import i18n from "discourse-common/helpers/i18n";
|
||||
|
||||
export default class WelcomeBanner extends Component {
|
||||
@service router;
|
||||
|
@ -84,12 +85,12 @@ export default class WelcomeBanner extends Component {
|
|||
<div class="hero-buttons">
|
||||
<DButton
|
||||
@action={{this.router.transitionTo "login"}}
|
||||
@label={{settings.login_button_text}}
|
||||
@label={{i18n "welcome_banner.buttons.login"}}
|
||||
class="btn-primary hero-login-btn"
|
||||
/>
|
||||
<DButton
|
||||
@action={{this.router.transitionTo "signup"}}
|
||||
@label={{settings.register_button_text}}
|
||||
@label={{i18n "welcome_banner.buttons.register"}}
|
||||
class="btn-default hero-register-btn"
|
||||
/>
|
||||
</div>
|
||||
|
|
8
locales/en.yml
Normal file
8
locales/en.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
en:
|
||||
theme_metadata:
|
||||
description: "Welcome banner theme component for Nyíltvilág community"
|
||||
js:
|
||||
welcome_banner:
|
||||
buttons:
|
||||
login: "Log in"
|
||||
register: "Sign up"
|
8
locales/hu.yml
Normal file
8
locales/hu.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
hu:
|
||||
theme_metadata:
|
||||
description: "Üdvözlő banner téma komponens a Nyíltvilág közösség számára"
|
||||
js:
|
||||
welcome_banner:
|
||||
buttons:
|
||||
login: "Belépés"
|
||||
register: "Regisztráció"
|
14
settings.yml
14
settings.yml
|
@ -105,20 +105,6 @@ hero_content_anonymous_html:
|
|||
en: Hero section content for anonymous users (HTML allowed)
|
||||
hu: Hero szekció tartalma nem bejelentkezett felhasználóknak (HTML használható)
|
||||
|
||||
login_button_text:
|
||||
default: "Belépés"
|
||||
type: string
|
||||
description:
|
||||
en: Login button text for anonymous users
|
||||
hu: Belépés gomb szövege nem bejelentkezett felhasználóknak
|
||||
|
||||
register_button_text:
|
||||
default: "Regisztráció"
|
||||
type: string
|
||||
description:
|
||||
en: Register button text for anonymous users
|
||||
hu: Regisztráció gomb szövege nem bejelentkezett felhasználóknak
|
||||
|
||||
# =============================================================================
|
||||
# 🔍 SEARCH SETTINGS
|
||||
# =============================================================================
|
||||
|
|
Loading…
Reference in a new issue