# Jak řešit překlady flash zpráviček v Nette Framework

Sem tam chceme uživateli sdělit, že se něco stalo. V [Nette Frameworku](http://nette.org) je na to připravena podpora pomocí takzvaných [flash messages](http://doc.nette.org/cs/2.3/presenters#toc-flash-zpravy).

Nedávno jsem potřeboval vyřešit jejich multijazyčnou variantu a zde vám ukáži jak jsem to řešil.

## Klasika

Asi nejsnažší způsob, jak překládat flash message je přeložit jí v presenteru pomocí injectnutého translátoru. (viz článek [jak na multijazyčný web](http://blog.honzacerny.com/post/5-jak-na-multijazycny-web-s-nette-framework-a-kdyby-translation))

```
$this->flashMessage($this->translator->translate('flash.newArticleSuccess'));
```

Vše máme pod kontrolou a pokud potřebujeme do zprávy předat parametr nic nám v tom nebrání, případně změnit typ zprávy

```
$this->flashMessage($this->translator->translate('flash.deleteUser', ['username'=>$username]), 'success');
```

Tím by mohl článek skončit, ale opak je pravdou, zde teprve začínáme.

## Addons, extensions, rozšíření

Když jsem se kouknul na výsledný kód, připadalo mi, že by se to dalo používat trošku ne tak ukecaně. A je jasné, že nebudu první koho to napadlo :) Po chvilce hledání jsem narazil na dvě rozšíření

* IPub/FlashMessages - <http://addons.nette.org/ipub/flash-messages>
* librette/flash-messages - <https://github.com/librette/flash-messages/>

(Narazil jsem ještě na Zenify/FlashMessageComponent, ale u komponenty je DEPRECATED, tak jsem ji rovnou přeskočil)

Obě rozšíření mají composer balíček, takže jejich instalace byla velmi snadná.

## librette/flash-messages

Github: <https://github.com/librette/flash-messages/>

**Instalace**

`$ composer require librette/flash-messages @dev`

Po prozkoumání kódu zjistíte, že komponenta je velmi jednoduchá. Nebojte že nemá dokumentaci, její použití je snadné.

Začneme tak, že v našem presenteru použijeme [traitu](http://php.net/manual/en/language.oop5.traits.php) `TEnhancedFlashMessages` a přepíšeme metodu `getTranslator()`, kterou traita definuje a používá pro získání nějakého překladače.

```
use Librette\FlashMessages\TEnhancedFlashMessages;

class HomepagePresenter extends Nette\Application\UI\Presenter
{
    use TEnhancedFlashMessages;

    ...

    /** @var \Kdyby\Translation\Translator @inject */
    public $translator;

    protected function getTranslator()
    {
        return $this->translator;
    }
```

*(pro zjednodušení ukázky dávám kód do HomepagePresenteru ve vaší aplikaci to bude BasePresenter)*

Použití je pak snadné. Traita přepisuje nativní chování metody `flashMessage()` a přidává i parametry pro složitější překlady.

Následující ukázky snad nepotřebují více komentovat

```
    $this->flashMessage('ui.wow');
    $this->flashMessage('ui.wow', 'warning');
    $this->flashMessage('ui.wow', 'error');
    $this->flashMessage('ui.num', 'info', 3);
    $this->flashMessage('ui.name', 'success', ['name' => "Karel"]);
    $this->flashMessage('ui.numname', 'success', 3, ['name' => "Karel"]);
```

ukázkový slovník `ui.cs_CZ.neon`

```
wow: "tohle je fleš zpráva"
num: "tohle jedna |tohle je fleš zpráva %count%"
name: "kuk %name%"
numname: "tohle jedna %name% |tohle je fleš zpráva %count% od %name%"
```

Vykreslování v šabloně můžeme nechat defaultní

```
    <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">{$flash->message}</div>
```

A nebo použijeme druhou traitu, která v balíčku je a to `TFlashMessages`, která vytváří komponentu pro vykreslování flash message s přidáním tříd pro CSS Bootstrap 3.

```
use Librette\FlashMessages\TEnhancedFlashMessages;
use Librette\FlashMessages\Component\TFlashMessages;

class HomepagePresenter extends Nette\Application\UI\Presenter
{
    use TEnhancedFlashMessages;
    use TFlashMessages;

    ...
```

v šabloně použijeme

```
{control flashMessages}
```

Zde bych jen upozornil, že tato komponenta má šablonu připravenou pro CSS Boostrap 3 a řeší "přejmenování" typu `error` na css třídu `danger` což mi přijde super.

Ukázky různého volání najdete na [GitHub/chemix/try-flashmessage - librette](https://github.com/chemix/try-flashmessage/blob/master/librette/app/presenters/HomepagePresenter.php)

## IPub/FlashMessages

Github: <https://github.com/iPublikuj/flash-messages>

**Instalace**

`$ composer require ipub/flash-messages`

Tato komponenta má o dost více kodu nežli předchozí. Bonus jsou testy a dokumentace. Při letmém zkoumání (nebo z dokumentace) zjistíte, že se registruje do systému jako extension

```
extensions:
    flashMessages: IPub\FlashMessages\DI\FlashMessagesExtension
```

do presenteru si ji opět přidáme použitím traity.

```
use IPub\FlashMessages;

class HomepagePresenter extends Nette\Application\UI\Presenter
{
    use FlashMessages\TFlashMessages;
```

V šabloně je třeba **vždy** použít komponentu. (komponenta používá vlastní řešení pro storage zpráv)

```
{control flashMessages}
```

Poslání jednoduché zprávy je pak

```
    $this->flashMessage('ui.wow', 'danger');
```

Šablonu pro komponentu je možné změnit z defaultní na CSS Bootstrap nebo na UIkit v `config.neon`

```
flashMessages:
    templateFile: bootstrap
```

Komponenta má další dvě volby nastavení. Vypnutí/zapnutí "title" pro zprávu, a možnost takzvané overlay zprávy.

```
flashMessages:
    useTitle: TRUE  # defalní hodnota je TRUE
    useOverlay: TRUE
```

title:

\[ */data/articles/8/title.png 500x?* ]

overlay:

\[ */data/articles/8/overlay.png 800x?* ]

Bohužel na `title` zprávy se neaplikuje překladač, takže pokud jí chcete použít je třeba delší zápis (v1.0.1)

```
    $this->flashMessage('ui.wow', 'danger', $this->translator->translate('ui.error'));
```

Pokud chcete použít parametry pro překlad a nepoužít title je třeba ho přeskočit včetně přepínače pro overlay zprávu.

```
    $this->flashMessage('ui.num', 'info', NULL, FALSE, 1);
    $this->flashMessage('ui.name', 'success', NULL, FALSE, ['name' => "Karel"]);
```

To už tak pekně nevypadá.

Spolu s přepsanou metodou `flashMessege()` tato komponenta přichází s objektem `$this->flashNotifier`, který přináší pár zkratek, například:

```
    $this->flashNotifier->overlay('ui.wow');
    $this->flashNotifier->error('ui.wow');
```

Overlay jsem zkoušel s nastavenou šablonou pro Bootstrap, kde jsem si načetl nějaký JavaScript a postaral se zobrazení overlay zprávy.

```
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">

    ...

    <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
    <script n:syntax="double">
        $(function(){
            $('.modal').modal();
        });
    </script>
```

*(hodně lehká verze inicializace co nebude fungovat s flash zprávou a snippetem)*

Další výhodou této komponenty je, že traitu můžete použít ve vaší komponentě a odesílat flash zprávičky přímo z vaší komponenty. Toto v současné době řeším přes události co probublají do presenteru a ten se o flash message postará. Pokud pracujete hodně s komponentama imho velmi zajímavá vlastnost.

Ukázky různého volání najdete na [GitHub/chemix/try-flashmessage - ipublikuj](https://github.com/chemix/try-flashmessage/blob/master/ipublikuj/app/presenters/HomepagePresenter.php)

## Závěr

Díky [Adamovi Kadlecovi](https://github.com/akadlec) a [Davidu Matějkovi](https://github.com/matej21) za jejich komponenty.

Librette mi přijde pro mé potřeby jako dostatečné řešení. V IPub bych bral inspiraci, pokud bych potřeboval něco více. Na druhou stranu i použití IPub v projektu, kde je Bootstap a chcete posílat jen krátké zprávy není špatná cesta a pokud chcete občas poslat overlay zprávu, tak je to pěkné hotové řešení. Jen pořadí parametrů mi přijde nevhodně zvolené a to že "title" si musím případně překládat sám (v1.0.1).

Zdrojové soubory najdete na [GitHub/chemix/try-flashmessage ](https://github.com/chemix/try-flashmessage)

PS: Jak řešíte překlady flash zpráviček vy?


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.honzacerny.com/nette-framework/jak-resit-preklady-flash-zpravicek-v-nette-framework.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
