Prepinani jazyka a ErrorPresenter

M4RtY89
Člen | 7
+
0
-

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
+
0
-

@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
+
0
-

@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.

M4RtY89
Člen | 7
+
0
-

Dekuji moc za odpoved. Premyslel jsem jak to elegantne vyresit, muj cil je ten Translation plugin prizpusobit tak, aby to davalo nejvetsi smysl.

Zkusim pridat ty routu a uvidime, kam me to posune dale, pri nejhorsim vyradim prepinani jazyka pri zobrazeni Errorpresenteru.

Marek Bartoš
Nette Blogger | 1263
+
0
-

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
+
0
-

@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
+
-1
-

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
+
0
-

@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.