Prepinani jazyka a ErrorPresenter
- M4RtY89
- Člen | 7
Zdravim,
pouzivam pro preklady Contributte/Translation a pouzivam
translatorSessionResolver pro nastaveni locale. V teto casti
musim rict, ze vse funguje jak ma, locale se ulozi do session a mohu prepinat
mezi odkazy. Presunul jsem take ErrorPresenter i sablony do modulu, protoze
jsem chtel zobrazit chybove hlasky jako soucasti designu a ne samostatne
podstranky.
Tady nastava problem, pokud vyvolam chybu, napr 404, tak muj ErrorPresenter se vypise, samozrejme i s preklady (dle ulozeneho locale), ale nemohu prepinat jazyky.
Pro prestavu – prepinac jazyka mam v levem sloupci, ktery se vypisuje vzdy a u kazde podstranky, tj. i tehdy pokud se vyvola chyba a zobrazi ErrorPresenter.
1. Mam definovany BasePresenter, ve kterem mam signal pro prepnuti jazyka
/** @var Nette\Localization\ITranslator @inject */
public $translator;
/** @var Contributte\Translation\LocalesResolvers\Session @inject */
public $translatorSessionResolver;
public function startup() {
parent::startup();
}
public function handleChangeLocale(string $locale): void {
$this->translatorSessionResolver->setLocale($locale);
$this->redirect('this');
}
2. Mam dale definovany HomepagePresenter (a dalsi pro jednotlive stranky), ktere dedi z BasePresenteru, to stejne mam i pro Error4xxPresenter, ktery jsem presunul do modulu
final class HomepagePresenter extends BasePresenter {
private $database;
public function __construct(Nette\Database\Context $database) {
$this->database = $database;
}
public function renderDefault(): void {
}
}
3. Kdyz vyvolam chybu, zobrazi se „Stranka nenalezena“, s prekladem dle ulozeneho locale v Session, to je v poradku. Ovsem pokud chci v tom sloupci prepnout jazyk pres signal, tak se nic nestane a jen ze zobrazi stranka:
http://localhost/error4xx/?locale=en&do=ChangeLocale
Rad bych se zeptal na radu, co musim udelat pro to, abych byl schopen prepnout jazyk i pri vyvolane chybe? Co jsem se docetl je to, ze snad na ErrorPresenteru nefunguje routovani?
Dekuji za rady a omlouvam se za popis, zacinam s Nette :)
- m.brecher
- Generous Backer | 864
@M4RtY89
Ovsem pokud chci v tom sloupci prepnout jazyk pres signal
Ano, jednou už se tady na fóru řešilo, že v ErrorPresenteru nemohou z principu fungovat signály – tehdy @MarekBartoš vysvětlil, že ErrorPresenter nemá routu a proto v něm nemohou fungovat signály.
Už si detaily nepamatuju, ale myslím, že stačilo přidat routu pro ErrorPresenter a signály fungovaly + odblokovat normální requesty, které jsou v ErrorPresenteru z nette/web-project zablokované.
Jednodušší asi je komponentu, která signál používá z chybové stránky vyřadit.
Editoval m.brecher (5. 6. 2023 13:28)
- m.brecher
- Generous Backer | 864
@M4RtY89
chybove hlasky jako soucasti designu
to je správný postup, je vhodné aby chybové stránky zachovaly design webu. Ale z hlediska funkce není chybová stránka plnohodnotná stránka webu. Je to hlášení o chybě a je zbytečné tam umisťovat nějakém komponenty se signály.
- Marek Bartoš
- Nette Blogger | 1263
Jde to vyřešit celkem snadno. Error presenter naroutovat nejde, Nette to
aktivně blokuje. Co ale můžeš udělat je, že v error presenteru zavoláš
$this->forward()
, aby se ti zobrazil jiný presenter. V tom už
ti routing fungovat bude.
Akorát takový presenter bude mít fixní url adresu (např. /error) se kterou se budou generovat odkazy (nemělo by ničemu vadit) a stránka bude přístupná přes danou url a tak bys měl při přímém přístupu error simulovat:
class ExampleRoutableErrorPresenter extends Presenter
{
public function actionDefault(Throwable|null $throwable = null): void
{
$this->getHttpResponse()->setCode($this->getHttpCode($throwable));
// Note error in ajax request
if ($this->isAjax()) {
$this->payload->error = true;
$this->sendPayload();
}
}
private function getHttpCode(Throwable|null $throwable): mixed
{
// User error
if ($throwable instanceof BadRequestException) {
$code = $throwable->getCode();
if ($code >= 500) {
$code = IResponse::S500_InternalServerError;
} elseif ($code < 400) {
$code = IResponse::S404_NotFound;
}
return $code;
}
// Direct access, act as user error
if ($throwable === null) {
return IResponse::S404_NotFound;
}
// Real error
return IResponse::S500_InternalServerError;
}
}
- m.brecher
- Generous Backer | 864
@M4RtY89
pri nejhorsim vyradim prepinani jazyka pri zobrazeni Errorpresenteru
Ocení uživatel, že si na chybové stránce může přepnout jazykovou verzi? Ne, bude se chtít dostat k požadovaným informacím. Proto by se mu mělo na 404 stránce nabídnout navigační menu, popř. odkaz na homepage – ideálně v designu webu.
Takže podědit Error4xxPresenter z Basepresenteru je výborné + zablokovat v layoutu komponenty se signály. To je myslím nejjednodušší a přitom dobré řešení.
locale se ulozi do session a mohu prepinat mezi odkazy
Jestli jsem to pochopil správně, tak přepínání jazyků děláš tak, že komponenta přepínač jazyků pošle signálem požadavek na jazyk, ten se uloží do session a web si jazykovou verzi bere ze session ??
A nevzniká Ti takto na jednom url duplicita jazykových verzí ?? Není lepší klasický postup mít příslušný jazyk v url a komponenta přepínání mezi jazyky by pracovala s parametrem $lang/$locale v url? Potom by se to obešlo bez signálů.
Editoval m.brecher (5. 6. 2023 19:24)
- M4RtY89
- Člen | 7
Jestli jsem to pochopil správně, tak přepínání jazyků děláš tak, že komponenta přepínač jazyků pošle signálem požadavek na jazyk, ten se uloží do session a web si jazykovou verzi bere ze session ??
Ano to je pravda, do SESSION se ulozi parametr locale a udela se redirect($this), takze refresh stranky, a to je presne taky to, co se snazim vychytat, koukal jsem na routovani a napadlo me zkusit upravit routu tak, abych tam pridal paramter locale a podle toho se do URL vlozil EN nebo CZ nazev stranky.
Kdyz to reknu uplne hloupe, prijde mi vice elegantni nemit v URL „CS“ nebo „EN“, a kdyz Contributte/Translation nabizi ukladat jazyk do SESSION, chtel jsem to zkusit – tim netvrdim, ze u toho zustanu :)
- m.brecher
- Generous Backer | 864
@M4RtY89
prijde mi vice elegantni nemit v URL „CS“ nebo „EN“
V administraci dejme tomu s malou výhradou OK, ale na veřejném webu to je úplně špatně – různý obsah na stejném url, to je ještě daleko horší než duplicita url.
Ale i v administraci je lepší mít v url pořádek, obsah : url mapovat 1 : 1. Výhody nemít v url jazyk nevidím žádné.
Do session bych ukládal nějaká custom nastavení designu, nebo vykreslovacích šablon, které nemění obsah jako takový, ale jenom jeho formu. Ale parametry, které definují obsah jako takový je nejlepší mít v url.