diff --git a/.gitattributes b/.gitattributes
index 3aa6270af..d1b8bb648 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,9 +1,9 @@
.gitattributes export-ignore
.gitignore export-ignore
.github export-ignore
-.travis.yml export-ignore
-ecs.php export-ignore
+ncs.* export-ignore
phpstan.neon export-ignore
+docs/ export-ignore
tests/ export-ignore
*.sh eol=lf
diff --git a/docs/cs/@home.texy b/docs/cs/@home.texy
new file mode 100644
index 000000000..2de7d51f3
--- /dev/null
+++ b/docs/cs/@home.texy
@@ -0,0 +1,24 @@
+Dependency Injection
+********************
+
+.[perex]
+Balíček `nette/di` poskytuje nesmírně pokročilý kompilovaný DI kontejner pro PHP.
+
+- [Co je Dependency Injection? |introduction]
+- [Co je DI kontejner? |container]
+- [Nette DI Container |nette-container]
+- [Konfigurace |configuration]
+- [Definování služeb |services]
+- [Autowiring |autowiring]
+- [Generované továrny |factory]
+- [Předávání závislostí |passing-dependencies]
+- [Tvorba rozšíření pro Nette DI|extensions]
+
+
+Instalace:
+
+```shell
+composer require nette/di
+```
+
+{{composer: nette/di}}
diff --git a/docs/cs/@left-menu.texy b/docs/cs/@left-menu.texy
new file mode 100644
index 000000000..9502085ab
--- /dev/null
+++ b/docs/cs/@left-menu.texy
@@ -0,0 +1,13 @@
+
+
+Dependency Injection
+--------------------
+- [Co je DI? |introduction]
+- [Co je DI kontejner? |container]
+- [Nette DI Container |nette-container]
+- [Konfigurace |configuration]
+- [Definování služeb |services]
+- [Autowiring |autowiring]
+- [Generované továrny |factory]
+- [Předávání závislostí |passing-dependencies]
+- [Tvorba rozšíření pro Nette DI|extensions]
diff --git a/docs/cs/autowiring.texy b/docs/cs/autowiring.texy
new file mode 100644
index 000000000..1f23c8583
--- /dev/null
+++ b/docs/cs/autowiring.texy
@@ -0,0 +1,233 @@
+Autowiring
+**********
+
+.[perex]
+Autowiring je skvělá vlastnost, která umí automaticky předávat do konstruktoru a dalších metod požadované služby, takže je nemusíme vůbec psát. Ušetří vám spoustu času.
+
+Díky tomu můžeme vynechat naprostou většinu argumentů při psaní definic služeb. Místo:
+
+```neon
+services:
+ articles: Model\ArticleRepository(@database, @cache.storage)
+```
+
+Stačí napsat:
+
+```neon
+services:
+ articles: Model\ArticleRepository
+```
+
+Autowiring se řídí podle typů, takže aby fungoval, musí být třída `ArticleRepository` definována asi takto:
+
+```php
+namespace Model;
+
+class ArticleRepository
+{
+ public function __construct(\PDO $db, \Nette\Caching\Storage $storage)
+ {}
+ public function setCacheStorage(\Nette\Caching\IStorage $storage)
+}
+```
+
+Aby bylo možné použit autowiring, musí pro každý typ být v kontejneru **právě jedna služba**. Pokud by jich bylo víc, autowiring by nevěděl, kterou z nich předat a vyhodil by výjimku:
+
+```neon
+services:
+ mainDb: PDO(%dsn%, %user%, %password%)
+ tempDb: PDO('sqlite::memory:')
+ articles: Model\ArticleRepository # VYHODÍ VÝJIMKU, vyhovuje mainDb i tempDb
+```
+
+Řešením by bylo buď autowiring obejít a explicitně uvést název služby (tj `articles: Model\ArticleRepository(@mainDb)`). Šikovnější ale je autowirování jedné ze služeb [vypnout|#Vypnutí autowiringu], nebo první službu [upřednostnit|#Preference autowiringu].
+
+
+Vypnutí autowiringu
+-------------------
+
+Autowirování služby můžeme vypnout pomocí volby `autowired: no`:
+
+```neon
+services:
+ mainDb: PDO(%dsn%, %user%, %password%)
+
+ tempDb:
+ create: PDO('sqlite::memory:')
+ autowired: false # služba tempDb je vyřazena z autowiringu
+
+ articles: Model\ArticleRepository # tudíž předá do kontruktoru mainDb
+```
+
+Služba `articles` nevyhodí výjimku, že existují dvě vyhovující služby typu `PDO` (tj. `mainDb` a `tempDb`), které lze do konstruktoru předat, protože vidí jen službu `mainDb`.
+
+
+Preference autowiringu
+----------------------
+
+Pokud máme více služeb stejného typu a u jedné z nich uvedeme volbu `autowired`, stává se tato služba preferovanou:
+
+```neon
+services:
+ mainDb:
+ create: PDO(%dsn%, %user%, %password%)
+ autowired: PDO # stává se preferovanou
+
+ tempDb:
+ create: PDO('sqlite::memory:')
+
+ articles: Model\ArticleRepository
+```
+
+Služba `articles` nevyhodí výjimku, že existují dvě vyhovující služby typu `PDO` (tj. `mainDb` a `tempDb`), ale použije preferovanou službu, tedy `mainDb`.
+
+
+Pole služeb
+-----------
+
+Autowiring umí předávat i pole služeb určitého typu. Protože v PHP nelze nativně zapsat typ položek pole, je třeba kromě typu `array` doplnit i phpDoc komentář s typem položky ve tvaru `ClassName[]`:
+
+```php
+namespace Model;
+
+class ShipManager
+{
+ /**
+ * @param Shipper[] $shippers
+ */
+ public function __construct(array $shippers)
+ {}
+}
+```
+
+DI kontejner pak automaticky předá pole služeb odpovídajících danému typu. Vynechá služby, které mají vypnutý autowiring.
+
+Pokud nemůžete ovlivnit podobu phpDoc komentáře, můžete předat pole služeb přímo v konfiguraci pomocí [`typed()`|services#Speciální funkce].
+
+
+Zúžení autowiringu
+------------------
+
+Jednotlivým službám lze autowiring zúžit jen na určité třídy nebo rozhraní.
+
+Normálně autowiring službu předá do každého parametru metody, jehož typu služba odpovídá. Zúžení znamená, že stanovíme podmínky, kterým musí typy uvedené u parametrů metod vyhovovat, aby jim byla služba předaná.
+
+Ukážeme si to na příkladu:
+
+```php
+class ParentClass
+{}
+
+class ChildClass extends ParentClass
+{}
+
+class ParentDependent
+{
+ function __construct(ParentClass $obj)
+ {}
+}
+
+class ChildDependent
+{
+ function __construct(ChildClass $obj)
+ {}
+}
+```
+
+Pokud bychom je všechny zaregistrovali jako služby, tak by autowiring selhal:
+
+```neon
+services:
+ parent: ParentClass
+ child: ChildClass
+ parentDep: ParentDependent # VYHODÍ VÝJIMKU, vyhovují služby parent i child
+ childDep: ChildDependent # autowiring předá do konstruktoru službu child
+```
+
+Služba `parentDep` vyhodí výjimku `Multiple services of type ParentClass found: parent, child`, protože do jejího kontruktoru pasují obě služby `parent` i `child`, a autowiring nemůže rozhodnout, kterou z nich zvolit.
+
+U služby `child` můžeme proto zúžit její autowirování na typ `ChildClass`:
+
+```neon
+services:
+ parent: ParentClass
+ child:
+ create: ChildClass
+ autowired: ChildClass # lze napsat i 'autowired: self'
+
+ parentDep: ParentDependent # autowiring předá do konstruktoru službu parent
+ childDep: ChildDependent # autowiring předá do konstruktoru službu child
+```
+
+Nyní se do kontruktoru služby `parentDep` předá služba `parent`, protože teď je to jediný vyhovující objekt. Službu `child` už tam autowiring nepředá. Ano, služba `child` je stále typu `ParentClass`, ale už neplatí zužující podmínka daná pro typ parametru, tj. neplatí, že `ParentClass` *je nadtyp* `ChildClass`.
+
+U služby `child` by bylo možné `autowired: ChildClass` zapsat také jako `autowired: self`, jelikož `self` je zástupné označení pro třídu aktuální služby.
+
+V klíči `autowired` je možné uvést i několik tříd nebo interfaců jako pole:
+
+```neon
+autowired: [BarClass, FooInterface]
+```
+
+Zkusme příklad doplnit ještě o rozhraní:
+
+```php
+interface FooInterface
+{}
+
+interface BarInterface
+{}
+
+class ParentClass implements FooInterface
+{}
+
+class ChildClass extends ParentClass implements BarInterface
+{}
+
+class FooDependent
+{
+ function __construct(FooInterface $obj)
+ {}
+}
+
+class BarDependent
+{
+ function __construct(BarInterface $obj)
+ {}
+}
+
+class ParentDependent
+{
+ function __construct(ParentClass $obj)
+ {}
+}
+
+class ChildDependent
+{
+ function __construct(ChildClass $obj)
+ {}
+}
+```
+
+Když službu `child` nijak neomezíme, bude pasovat do konstruktorů všech tříd `FooDependent`, `BarDependent`, `ParentDependent` i `ChildDependent` a autowiring ji tam předá.
+
+Pokud její autowiring ale zúžíme na `ChildClass` pomocí `autowired: ChildClass` (nebo `self`), předá ji autowiring pouze do konstruktoru `ChildDependent`, protože vyžaduje argument typu `ChildClass` a platí, že `ChildClass` *je typu* `ChildClass`. Žádný další typ uvedený u dalších parametrů není nadtypem `ChildClass`, takže se služba nepředá.
+
+Pokud jej omezíme na `ParentClass` pomocí `autowired: ParentClass`, předá ji autowiring opět do konstruktoru `ChildDependent` (protože vyžadovaný `ChildClass` je nadtyp `ParentClass` a nově i do konstruktoru `ParentDependent`, protože vyžadovaný typ `ParentClass` je taktéž vyhovující.
+
+Pokud jej omezíme na `FooInterface`, bude stále autowirovaná do `ParentDependent` (vyžadovaný `ParentClass` je nadtyp `FooInterface`) a `ChildDependent`, ale navíc i do konstruktoru `FooDependent`, nikoliv však do `BarDependent`, neboť `BarInterface` není nadtyp `FooInterface`.
+
+```neon
+services:
+ child:
+ create: ChildClass
+ autowired: FooInterface
+
+ fooDep: FooDependent # autowiring předá do konstruktoru child
+ barDep: BarDependent # VYHODÍ VÝJIMKU, žádná služba nevyhovuje
+ parentDep: ParentDependent # autowiring předá do konstruktoru child
+ childDep: ChildDependent # autowiring předá do konstruktoru child
+```
+
+
+{{composer: nette/di}}
diff --git a/docs/cs/configuration.texy b/docs/cs/configuration.texy
new file mode 100644
index 000000000..5308d773c
--- /dev/null
+++ b/docs/cs/configuration.texy
@@ -0,0 +1,314 @@
+Konfigurace DI kontejneru
+*************************
+
+.[perex]
+Přehled konfiguračních voleb pro Nette DI kontejner.
+
+Nette DI kontejner se snadno ovládá pomocí konfiguračních souborů. Ty se obvykle zapisují ve [formátu NEON|/neon/format]. K editaci doporučujeme [editory s podporou|/best-practices/editors-and-tools#ide-editor] tohoto formátu.
+
+
+"decorator .[prism-token prism-atrule]":[#decorator]: "Dekorátor .[prism-token prism-comment]"
+"di .[prism-token prism-atrule]":[#DI]: "DI kontejner .[prism-token prism-comment]"
+"extensions .[prism-token prism-atrule]":[#Rozšíření]: "Instalace dalších DI rozšíření .[prism-token prism-comment]"
+"includes .[prism-token prism-atrule]":[#Vkládání souborů]: "Vkládání souborů .[prism-token prism-comment]"
+"parameters .[prism-token prism-atrule]":[#parametry]: "Parametry .[prism-token prism-comment]"
+"search .[prism-token prism-atrule]":[#Search]: "Automatická registrace služeb .[prism-token prism-comment]"
+"services .[prism-token prism-atrule]":[services]: "Služby .[prism-token prism-comment]"
+
+
+Chcete-li zapsat řetězec začínající znakem `@` nebo obsahující `%`, musíte znak escapovat zdvojením na `@@` nebo `%%`. .[note]
+
+
+Parametry
+=========
+
+V konfiguraci můžete definovat parametry, které lze pak použít jako součást definic služeb. Čímž můžete zpřehlednit konfiguraci nebo sjednotit a vyčlenit hodnoty, které se budou měnit.
+
+```neon
+parameters:
+ dsn: 'mysql:host=127.0.0.1;dbname=test'
+ user: root
+ password: secret
+```
+
+Na parametr `dsn` se odkážeme kdekoliv v konfiguraci zápisem `%dsn%`. Parametry lze používat i uvnitř řetězců jako `'%wwwDir%/images'`.
+
+Parametry nemusí být jen řetězce nebo čísla, mohou také obsahovat pole:
+
+```neon
+parameters:
+ mailer:
+ host: smtp.example.com
+ secure: ssl
+ user: franta@gmail.com
+ languages: [cs, en, de]
+```
+
+Na konkrétní klíč se odkážeme jako `%mailer.user%`.
+
+Pokud potřebujete ve vašem kódu, například třídě, zjistit hodnotu jakékoliv parametru, tak jej do této třídy předejte. Například v konstruktoru. Neexistuje žádný globální objekt představující konfiguraci, kterého by se třídy dotazovaly na hodnoty parametrů. To by bylo porušením principu dependency injection.
+
+
+Služby
+======
+
+Viz [samostatná kapitola|services].
+
+
+Decorator
+=========
+
+Jak upravit hromadně všechny služby určitého typu? Třeba zavolat určitou metodu u všech presenterů, které dědí od konkrétního společného předka? Od toho je tu decorator.
+
+```neon
+decorator:
+ # u všech služeb, co jsou instancí této třídy nebo rozhraní
+ App\Presenters\BasePresenter:
+ setup:
+ - setProjectId(10) # zavolej tuto metodu
+ - $absoluteUrls = true # a nastav proměnnou
+```
+
+Decorator se dá používat také pro nastavení [tagů|services#Tagy] nebo zapnutí režimu [inject|services#Režim Inject].
+
+```neon
+decorator:
+ InjectableInterface:
+ tags: [mytag: 1]
+ inject: true
+```
+
+
+DI
+===
+
+Technické nastavení DI kontejneru.
+
+```neon
+di:
+ # zobrazit DIC v Tracy Bar?
+ debugger: ... # (bool) výchozí je true
+
+ # typy parametrů, které nikdy neautowirovat
+ excluded: ... # (string[])
+
+ # třída, od které dědí DI kontejner
+ parentClass: ... # (string) výchozí je Nette\DI\Container
+```
+
+
+Export metadat
+--------------
+
+Třída DI kontejneru obsahuje i spoustu metadat. Můžete ji zmenšit tím, že export metadat zredukujete.
+
+```neon
+di:
+ export:
+ # exportovat parametry?
+ parameters: false # (bool) výchozí je true
+
+ # exportovat tagy a které?
+ tags: # (string[]|bool) výchozí jsou všechny
+ - event.subscriber
+
+ # exportovat data pro autowiring a které?
+ types: # (string[]|bool) výchozí jsou všechny
+ - Nette\Database\Connection
+ - Symfony\Component\Console\Application
+```
+
+Pokud nevyužíváte pole `$container->parameters`, můžete vypnout export parametrů. Dále můžete exportovat jen ty tagy, přes které získáváte služby metodou `$container->findByTag(...)`.
+Pokud metodu nevoláte vůbec, můžete zcela vypnout export tagů pomocí `false`.
+
+Výrazně můžete zredukovat metadata pro [autowiring] tím, že uvedete třídy, které používáte jako parametr metody `$container->getByType()`.
+A opět, pokud metodu nevoláte vůbec (resp. jen v [bootstrapu|/application/bootstrap] pro získání `Nette\Application\Application`), můžete export úplně vypnout pomocí `false`.
+
+
+Rozšíření
+=========
+
+Registrace dalších DI rozšíření. Tímto způsobem přidáme např. DI rozšíření `Dibi\Bridges\Nette\DibiExtension22` pod názvem `dibi`
+
+```neon
+extensions:
+ dibi: Dibi\Bridges\Nette\DibiExtension22
+```
+
+Následně ho tedy konfigurujeme v sekci `dibi`:
+
+```neon
+dibi:
+ host: localhost
+```
+
+Jako rozšíření lze přidat i třídu, která má parametry:
+
+```neon
+extensions:
+ application: Nette\Bridges\ApplicationDI\ApplicationExtension(%debugMode%, %appDir%, %tempDir%/cache)
+```
+
+
+Vkládání souborů
+================
+
+Další konfigurační soubory můžeme vložit v sekci `includes`:
+
+```neon
+includes:
+ - parameters.php
+ - services.neon
+ - presenters.neon
+```
+
+Název `parameters.php` není překlep, konfigurace může být zapsaná také v PHP souboru, který ji vrátí jako pole:
+
+```php
+ [
+ 'main' => [
+ 'dsn' => 'sqlite::memory:',
+ ],
+ ],
+];
+```
+
+Pokud se v konfiguračních souborech objeví prvky se stejnými klíči, budou přepsány, nebo v případě [polí sloučeny |#Slučování]. Později vkládaný soubor má vyšší prioritu než předchozí. Soubor, ve kterém je sekce `includes` uvedena, má vyšší prioritu než v něm vkládané soubory.
+
+
+Search
+======
+
+Automatické přidávání služeb do DI kontejneru nesmírně zpříjemňuje práci. Nette automaticky přidává do kontejneru presentery, lze však snadno přidávat i jakékoliv jiné třídy.
+
+Stačí uvést, ve kterých adresářích (a podadresářích) má třídy hledat:
+
+```neon
+search:
+ # názvy sekcí si volíte sami
+ formuláře:
+ in: %appDir%/Forms
+
+ model:
+ in: %appDir%/Model
+```
+
+Obvykle ovšem nechceme přidávat úplně všechny třídy a rozhraní, proto je můžeme filtrovat:
+
+```neon
+search:
+ formuláře:
+ in: %appDir%/Forms
+
+ # filtrování podle názvu souboru (string|string[])
+ files:
+ - *Factory.php
+
+ # filtrování podle názvu třídy (string|string[])
+ classes:
+ - *Factory
+```
+
+Nebo můžeme vybírat třídy, které dědí či implementují alespoň jednu z uvedených tříd:
+
+
+```neon
+search:
+ formuláře:
+ extends:
+ - App\*Form
+ implements:
+ - App\*FormInterface
+```
+
+Lze definovat i vylučující pravidla, tj. masky názvu třídy nebo dědičné předky, které pokud vyhovují, služba se do DI kontejneru nepřidá:
+
+```neon
+search:
+ formuláře:
+ exclude:
+ classes: ...
+ extends: ...
+ implements: ...
+```
+
+Všem službám lze nastavit tagy:
+
+```neon
+search:
+ formuláře:
+ tags: ...
+```
+
+
+Slučování
+=========
+
+Pokud se ve více konfiguračních souborech objeví prvky se stejnými klíči, budou přepsány, nebo v případě polí sloučeny. Později vkládaný soubor má vyšší prioritu než předchozí.
+
+
+
+ config1.neon |
+ config2.neon |
+ výsledek |
+
+
+
+```neon
+items:
+ - 1
+ - 2
+```
+ |
+
+```neon
+items:
+ - 3
+```
+ |
+
+```neon
+items:
+ - 1
+ - 2
+ - 3
+```
+ |
+
+
+
+U polí lze zabránit slučování uvedením vykřičníku za názvem klíče:
+
+
+
+ config1.neon |
+ config2.neon |
+ výsledek |
+
+
+
+```neon
+items:
+ - 1
+ - 2
+```
+ |
+
+```neon
+items!:
+ - 3
+```
+ |
+
+```neon
+items:
+ - 3
+```
+ |
+
+
+
+{{composer: nette/di}}
+{{maintitle: Konfigurace Dependency Injection}}
diff --git a/docs/cs/container.texy b/docs/cs/container.texy
new file mode 100644
index 000000000..e76015e2b
--- /dev/null
+++ b/docs/cs/container.texy
@@ -0,0 +1,146 @@
+Co je DI kontejner?
+*******************
+
+.[perex]
+Dependency injection kontejner (DIC) je třída, která umí instancovat a konfigurovat objekty.
+
+Možná vás to překvapí, ale v mnoha případech nepotřebujete dependency injection kontejner, abyste mohli využívat výhod dependency injection (krátce DI). Vždyť i v [předchozí kapitole|introduction] jsme si na konkrétních příkladech DI ukázali a žádný kontejner nebyl potřeba.
+
+Pokud však potřebujete spravovat velké množství různých objektů s mnoha závislostmi, bude dependency injection container opravdu užitečný. Což je třeba případ webových aplikací postavených na frameworku.
+
+V předchozí kapitole jsme si představili třídy `Article` a `UserController`. Obě mají nějaké závislosti, a to databázi a továrnu `ArticleFactory`. A pro tyto třídy si nyní vytvoříme kontejner. Samozřejmě pro tak jednoduchý příklad nemá smysl mít kontejner. Ale vytvoříme ho, abychom si ukázali, jak vypadá a funguje.
+
+Zde je jednoduchý hardcoded kontejner pro uvedený příklad:
+
+```php
+class Container
+{
+ public function createDatabase(): Nette\Database\Connection
+ {
+ return new Nette\Database\Connection('mysql:', 'root', '***');
+ }
+
+ public function createArticleFactory(): ArticleFactory
+ {
+ return new ArticleFactory($this->createDatabase());
+ }
+
+ public function createUserController(): UserController
+ {
+ return new UserController($this->createArticleFactory());
+ }
+}
+```
+
+Použití by vypadalo následovně:
+
+```php
+$container = new Container;
+$controller = $container->createUserController();
+```
+
+Kontejneru se pouze zeptáme na objekt a již nemusíme vědět nic o tom, jak jej vytvořit a jaké má závislosti; to všechno ví kontejner. Závislosti jsou kontejnerem injektovány automaticky. V tom je jeho síla.
+
+Kontejner má zatím zapsané všechny údaje navrdo. Uděláme tedy další krok a přidáme parametry, aby byl kontejner skutečně užitečný:
+
+```php
+class Container
+{
+ private $parameters;
+
+ public function __construct(array $parameters)
+ {
+ $this->parameters = $parameters;
+ }
+
+ public function createDatabase(): Nette\Database\Connection
+ {
+ return new Nette\Database\Connection(
+ $this->parameters['db.dsn'],
+ $this->parameters['db.user'],
+ $this->parameters['db.password']
+ );
+ }
+
+ // ...
+}
+
+$container = new Container([
+ 'db.dsn' => 'mysql:',
+ 'db.user' => 'root',
+ 'db.password' => '***',
+]);
+```
+
+Bystří čtenáři si možná všimli jistého problému. Pokaždé, když získám objekt `UserController`, vytvoří se také nová instance `ArticleFactory` a databáze. To rozhodně nechceme.
+
+Přidáme proto metodu `getService()`, která bude vracet stále stejné instance:
+
+```php
+class Container
+{
+ private $parameters;
+ private $services = [];
+
+ public function __construct(array $parameters)
+ {
+ $this->parameters = $parameters;
+ }
+
+ public function getService(string $name): object
+ {
+ if (!isset($this->services[$name])) {
+ // getService('Database') bude volat createDatabase()
+ $method = 'create' . $name;
+ $this->services[$name] = $this->$method();
+ }
+ return $this->services[$name];
+ }
+
+ // ...
+}
+```
+
+Při prvním volání např. `$container->getService('Database')` si nechá od `createDatabase()` vytvořit objekt databáze, který uloží do pole `$services` a při příštím volání jej rovnou vrátí.
+
+Upravíme i zbytek kontejneru, aby používal `getService()`:
+
+```php
+class Container
+{
+ // ...
+
+ public function createArticleFactory(): ArticleFactory
+ {
+ return new ArticleFactory($this->getService('Database'));
+ }
+
+ public function createUserController(): UserController
+ {
+ return new UserController($this->getService('ArticleFactory'));
+ }
+}
+```
+
+Mimochodem, termínem služba se označuje jakýkoliv objekt spravovaný kontejnerem. Proto i ten název metody `getService()`.
+
+Hotovo. Máme plně funkční DI kontejner! A můžeme ho použít:
+
+```php
+$container = new Container([
+ 'db.dsn' => 'mysql:',
+ 'db.user' => 'root',
+ 'db.password' => '***',
+]);
+
+$controller = $container->getService('UserController');
+$database = $container->getService('Database');
+```
+
+Jak vidíte, napsat DIC není nic složitého. Za připomenutí stojí, že samotné objekty neví, že je vytváří nějaký kontejner. Tím pádem je možné takto vytvářet jakýkoliv objekt v PHP bez zásahu do jeho zdrojového kódu.
+
+Ruční vytváření a údržba třídy kontejneru se může poměrně rychle stát noční můrou. V další kapitole si proto povíme o [Nette DI Containeru|nette-container], který se umí generovat a aktualizovat téměř sám.
+
+
+{{composer: nette/di}}
+{{maintitle: Co je dependency injection kontejner?}}
diff --git a/docs/cs/extensions.texy b/docs/cs/extensions.texy
new file mode 100644
index 000000000..69122350e
--- /dev/null
+++ b/docs/cs/extensions.texy
@@ -0,0 +1,197 @@
+Tvorba rozšíření pro Nette DI
+*****************************
+
+.[perex]
+Generování DI kontejneru kromě konfiguračních souborů ovlivňují ještě tzv *rozšíření*. Aktivujeme je v konfiguračním souboru v sekci `extensions`.
+
+Takto přidáme rozšíření reprezentované třídou `BlogExtension` pod názvem `blog`:
+
+```neon
+extensions:
+ blog: BlogExtension
+```
+
+Každé rozšíření kompileru dědí od [api:Nette\DI\CompilerExtension] a může implementovat následující metody, které jsou postupně volány během sestavování DI kontejneru:
+
+1. getConfigSchema()
+2. loadConfiguration()
+3. beforeCompile()
+4. afterCompile()
+
+
+getConfigSchema() .[method]
+===========================
+
+Tato metoda se volá jako první. Definuje schema pro validaci konfiguračních parametrů.
+
+Rozšíření konfigurujeme v sekci, jejíž název je stejný jako ten, pod kterým bylo rozšíření přidáno, tedy `blog`:
+
+```neon
+# stejné jméno jako má extension
+blog:
+ postsPerPage: 10
+ allowComments: false
+```
+
+Vytvoříme schema popisující všechny konfigurační volby včetně jejich typů, povolených hodnot a případně i výchozích hodnot:
+
+```php
+use Nette\Schema\Expect;
+
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function getConfigSchema(): Nette\Schema\Schema
+ {
+ return Expect::structure([
+ 'postsPerPage' => Expect::int(),
+ 'allowComments' => Expect::bool()->default(true),
+ ]);
+ }
+}
+```
+
+Dokumentaci najdete na stránce [/schema/@home]. Navíc lze určit, které volby mohou být [dynamické|/application/bootstrap#Dynamické parametry] pomocí `dynamic()`, např. `Expect::int()->dynamic()`.
+
+Ke konfiguraci se dostaneme přes proměnnou `$this->config`, což je objekt `stdClass`:
+
+```php
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function loadConfiguration()
+ {
+ $num = $this->config->postPerPage;
+ if ($this->config->allowComments) {
+ // ...
+ }
+ }
+}
+```
+
+
+loadConfiguration() .[method]
+=============================
+
+Používá se přidání služeb do kontejneru. K tomu slouží [api:Nette\DI\ContainerBuilder]:
+
+```php
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function loadConfiguration()
+ {
+ $builder = $this->getContainerBuilder();
+ $builder->addDefinition($this->prefix('articles'))
+ ->setFactory(App\Model\HomepageArticles::class, ['@connection'])
+ ->addSetup('setLogger', ['@logger']);
+ }
+}
+```
+
+Konvence je prefixovat služby přidané rozšířením jeho názvem, aby nevznikaly jmenné konflikty. To dělá metoda `prefix()`, takže pokud se rozšíření jmenuje `blog`, služba ponese název `blog.articles`.
+
+Pokud potřebujeme přejmenovat službu, můžeme kvůli zachování zpětné kompatibility vytvořit alias s původním názvem. Podobně to dělá Nette např. u služby `routing.router`, která je dostupná i pod dřívějším názvem `router`.
+
+```php
+$builder->addAlias('router', 'routing.router');
+```
+
+
+Načtení služeb ze souboru
+-------------------------
+
+Služby nemusíme vytvářet jen pomocí API třídy ContainerBuilder, ale i známým zápisem používaným v konfiguračním souboru NEON v sekci services. Prefix `@extension` představuje aktuální extension.
+
+```neon
+services:
+ articles:
+ create: MyBlog\ArticlesModel(@connection)
+
+ comments:
+ create: MyBlog\CommentsModel(@connection, @extension.articles)
+
+ articlesList:
+ create: MyBlog\Components\ArticlesList(@extension.articles)
+```
+
+Služby načteme:
+
+```php
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function loadConfiguration()
+ {
+ $builder = $this->getContainerBuilder();
+
+ // načtení konfiguračního souboru pro rozšíření
+ $this->compiler->loadDefinitionsFromConfig(
+ $this->loadFromFile(__DIR__ . '/blog.neon')['services'],
+ );
+ }
+}
+```
+
+
+beforeCompile() .[method]
+=========================
+
+Metoda se volá ve chvíli, kdy kontejner obsahuje všechny služby přidané jednotlivými rozšířeními v metodách `loadConfiguration` a taktéž uživatelskými konfiguračními soubory. V této fázi sestavování tedy můžeme definice služeb upravovat nebo doplnit vazby mezi nimi. Pro vyhledávání služeb v kontejneru podle tagů lze využít metodu `findByTag()`, podle třídy či rozhraní zase metodu `findByType()`.
+
+```php
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function beforeCompile()
+ {
+ $builder = $this->getContainerBuilder();
+
+ foreach ($builder->findByTag('logaware') as $serviceName => $tagValue) {
+ $builder->getDefinition($serviceName)->addSetup('setLogger');
+ }
+ }
+}
+```
+
+
+afterCompile() .[method]
+========================
+
+V této fázi už je třída kontejneru vygenerována v podobě objektu [ClassType |/php-generator/@home#tridy], obsahuje všechny metody, které vytváří služby, a je připravena na zápis do cache. Výsledný kód třídy můžeme v této chvíli ještě upravit.
+
+```php
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function afterCompile(Nette\PhpGenerator\ClassType $class)
+ {
+ $method = $class->getMethod('__construct');
+ // ...
+ }
+}
+```
+
+
+$initialization .[wiki-method]
+==============================
+
+Třída Configurator po [vytvoření kontejneru |/application/bootstrap#index.php] volá inicializační kód, který se vytváří zápisem do objektu `$this->initialization` pomocí [metody addBody() |/php-generator/@home#Generování těl metod a funkcí].
+
+Ukážeme si příklad, jak třeba inicializačním kódem nastartovat session nebo spustit služby, které mají tag `run`:
+
+```php
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function loadConfiguration()
+ {
+ // automatické startování session
+ if ($this->config->session->autoStart) {
+ $this->initialization->addBody('$this->getService("session")->start()');
+ }
+
+ // služby s tagem run musejí být vytvořeny po instancování kontejneru
+ $builder = $this->getContainerBuilder();
+ foreach ($builder->findByTag('run') as $name => $foo) {
+ $this->initialization->addBody('$this->getService(?);', [$name]);
+ }
+ }
+}
+```
+
+
+{{composer: nette/di}}
diff --git a/docs/cs/factory.texy b/docs/cs/factory.texy
new file mode 100644
index 000000000..a8fe2c95c
--- /dev/null
+++ b/docs/cs/factory.texy
@@ -0,0 +1,172 @@
+Generované továrny
+******************
+
+.[perex]
+Nette DI umí automaticky generovat kód továren na základě rozhraní, což vám ušetří psaní kódu.
+
+Továrna je třída, která vyrábí a konfiguruje objekty. Předává jim tedy i jejich závislosti. Jak taková továrna vypadá jsme si ukázali v [úvodní kapitole|introduction#továrna]:
+
+```php
+class ArticleFactory
+{
+ private Nette\Database\Connection $db;
+
+ public function __construct(Nette\Database\Connection $db)
+ {
+ $this->db = $db;
+ }
+
+ public function create(): Article
+ {
+ return new Article($this->db);
+ }
+}
+```
+
+Nette DI umí kód továren automaticky generovat. Vše, co musíte udělat, je vytvořit rozhraní a Nette DI vygeneruje implementaci. Rozhraní musí mít přesně jednu metodu s názvem `create` a deklarovat návratový typ:
+
+```php
+interface ArticleFactory
+{
+ function create(): Article;
+}
+```
+
+Tedy továrna `ArticleFactory` má metodu `create`, která vytváří objekty `Article`. Třída `Article` může vypadat třeba následovně:
+
+```php
+class Article
+{
+ private $db;
+
+ public function __construct(Nette\Database\Connection $db)
+ {
+ $this->db = $db;
+ }
+}
+```
+
+Továrnu přidáme do konfiguračního souboru:
+
+```neon
+services:
+ - ArticleFactory
+```
+
+Nette DI vygeneruje odpovídající implementaci továrny.
+
+V kódu, který továrnu používá, si tak vyžádáme objekt podle rozhraní a Nette DI použije vygenerovanou implementaci:
+
+```php
+class UserController
+{
+ private $articleFactory;
+
+ public function __construct(ArticleFactory $articleFactory)
+ {
+ $this->articleFactory = $articleFactory;
+ }
+
+ public function foo()
+ {
+ // necháme továrnu vytvořit objekt
+ $article = $this->articleFactory->create();
+ }
+}
+```
+
+
+Parametrizovaná továrna
+=======================
+
+Tovární metoda `create` může přijímat parametry, které poté předá do konstrukturu. Doplňme například třídu `Article` o ID autora článku:
+
+```php
+class Article
+{
+ private $db;
+ private $authorId;
+
+ public function __construct(Nette\Database\Connection $db, int $authorId)
+ {
+ $this->db = $db;
+ $this->authorId = $authorId;
+ }
+}
+```
+
+Parametr přidáme také do továrny:
+
+```php
+interface ArticleFactory
+{
+ function create(int $authorId): Article;
+}
+```
+
+Díky tomu, že se parametr v konstruktoru i parametr v továrně jmenují stejně, Nette DI je zcela automaticky předá.
+
+
+Pokročilá definice
+==================
+
+Definici lze zapsat i ve víceřádkové podobě za použití klíče `implement`:
+
+```neon
+services:
+ articleFactory:
+ implement: ArticleFactory
+```
+
+Při zápisu tímto delším způsobem je možné uvést další argumenty pro konstruktor v klíči `arguments` a doplňující konfiguraci pomocí `setup`, stejně, jako u běžných služeb.
+
+Příklad: pokud by metoda `create()` nepřijímala parametr `$authorId`, mohli bychom uvést pevnou hodnotu v konfiguraci, která by se předávala do konstruktoru `Article`:
+
+```neon
+services:
+ articleFactory:
+ implement: ArticleFactory
+ arguments:
+ authorId: 123
+```
+
+Nebo naopak pokud by `create()` parametr `$authorId` přijimala, ale nebyl by součástí konstruktoru a předával se metodou `Article::setAuthorId()`, odkázali bychom se na něj v sekci `setup`:
+
+```neon
+services:
+ articleFactory:
+ implement: ArticleFactory
+ setup:
+ - setAuthorId($authorId)
+```
+
+
+Accessor
+========
+
+Nette umí krom továren generovat i tzv. accessory. Jde o objekty s metodou `get()`, která vrací určitou službu z DI kontejneru. Opakované volání `get()` vrací stále tutéž instanci.
+
+Accessor poskytují závislostem lazy-loading. Mějme třídu, která zapisuje chyby do speciální databáze. Když by si tato třída nechávala připojení k databázi předávat jako závislost konstruktorem, muselo by se připojení vždycky vytvořit, ačkoliv v praxi se chyba objeví jen výjimečně a tedy povětšinou by zůstalo spojení nevyužité.
+Místo toho si tak třída předá accessor a teprve když se zavolá jeho `get()`, dojde k vytvoření objektu databáze:
+
+Jak accessor vytvořit? Stačí napsat rozhraní a Nette DI vygeneruje implementaci. Rozhraní musí mít přesně jednu metodu s názvem `get` a deklarovat návratový typ:
+
+```php
+interface PDOAccessor
+{
+ function get(): PDO;
+}
+```
+
+Accessor přidáme do konfiguračního souboru, kde je také definice služby, kterou bude vracet:
+
+```neon
+services:
+ - PDOAccessor
+ - PDO(%dsn%, %user%, %password%)
+```
+
+Protože accessor vrací službu typu `PDO` a v konfiguraci je jediná taková služba, bude vracet právě ji. Pokud by služeb daného typu bylo víc, určíme vracenou službu pomocí názvu, např. `- PDOAccessor(@db1)`.
+
+
+{{composer: nette/di}}
diff --git a/docs/cs/introduction.texy b/docs/cs/introduction.texy
new file mode 100644
index 000000000..7cc00ec80
--- /dev/null
+++ b/docs/cs/introduction.texy
@@ -0,0 +1,472 @@
+Co je Dependency Injection?
+***************************
+
+.[perex]
+Tato kapitola vás seznámí se základními programátorskými postupy, na kterých stojí celý framework Nette a které byste měli dodržovat při psaní vlastních aplikací. Jde o základy nutné pro psaní čistého, srozumitelného a udržitelného kódu.
+
+Pokud si tyto pravidla osvojíte a budete je dodržovat, bude vám framework v každém kroku vycházet vstříc. Bude za vás řešit rutinní úlohy a poskytne vám maximální pohodlí, abyste se mohli soustředit na samotnou logiku.
+
+Principy, které si zde ukážeme, jsou přitom celkem prosté. Nemusíte se ničeho obávat.
+
+
+Pamatujete na svůj první program?
+---------------------------------
+
+Netušíme sice, v jakém jazyce jste ho psali, ale kdyby to bylo PHP, nejspíš by vypadal nějak takto:
+
+```php
+function soucet(float $a, float $b): float
+{
+ return $a + $b;
+}
+
+echo soucet(23, 1); // vypíše 24
+```
+
+Pár triviálních řádků kódu, ale přitom se v nich skrývá tolik klíčových konceptů. Že existují proměnné. Že se kód člení do menších jednotek, což jsou kupříkladu funkce. Že jim předáváme vstupní argumenty a ony vracejí výsledky. Chybí tam už jen podmínky a cykly.
+
+To, že funkci předáme vstupní data a ona vrátí výsledek, je perfektně srozumitelný koncept, který se používá i v jiných oborech, jako je třeba v matematice.
+
+Funkce má svoji signaturu, kterou tvoří její název, přehled parametrů a jejich typů, a nakonec typ návratové hodnoty. Jako uživatele nás zajímá signatura, o vnitřní implementaci obvykle nepotřebujeme nic vědět.
+
+Teď si představte, že by signatura funkce vypadala takto:
+
+```php
+function soucet(float $x): float
+```
+
+Součet s jedním parametrem? To je divné… A co třeba takto?
+
+```php
+function soucet(): float
+```
+
+Tak to už je opravdu hodně divné, že? Jak se funkce asi používá?
+
+```php
+echo soucet(); // co asi vypíše?
+```
+
+Při pohledu na takový kód bychom byli zmateni. Nejen že by mu nerozuměl začátečník, takovému kódu nerozumí ani zdatný programátor.
+
+Přemýšlíte, jak by vlastně taková funkce vypadala uvnitř? Kde vezme sčítance? Zřejmě by si je *nějakým způsobem* obstarala sama, třeba takto:
+
+```php
+function soucet(): float
+{
+ $a = Input::get('a');
+ $b = Input::get('b');
+ return $a + $b;
+}
+```
+
+V těle funkce jsme objevili skryté vazby na další funkce (či statické metody) a abychom zjistili, odkud se skutečně sčítance berou, musíme pátrat dál.
+
+
+Tudy ne!
+--------
+
+Návrh, který jsme si právě ukázali, je esencí mnoha negativních rysů:
+
+- signatura funkce se tvářila, že nepotřebuje sčítance, což nás mátlo
+- vůbec nevíme, jak přimět funkci sečíst jiná dvě čísla
+- museli jsme se podívat do kódu, abychom zjistili, kde sčítance bere
+- objevili jsme skryté vazby
+- pro plné pochopení je třeba prozkoumat i tyto vazby
+
+A je vůbec úkolem sčítací funkce obstarávat si vstupy? Samozřejmě, že není. Její zodpovědností je pouze samotné sčítání.
+
+S takovým kódem se nechceme setkat, a rozhodně ho nechceme psát. Náprava je přitom jednoduchá: vrátit se k základům a prostě použít parametry:
+
+
+```php
+function soucet(float $a, float $b): float
+{
+ return $a + $b;
+}
+```
+
+
+Pravidlo č. 1: používej parametry
+---------------------------------
+
+Nejdůležitější pravidlo zní: **všechna data, která funkce nebo třídy potřebují, jim musíme předat**.
+
+Když tohle pravidlo porušíme, nebude možné dosáhnout toho, aby byl kód srozumitelný, čistý a dlouhodobě udržitelný.
+
+Když ho budeme dodržovat, jsme na cestě ke kódu bez skrytých vazeb. Ke kódu, který je srozumitelný nejen autorovi, ale i každému, kdo jej po něm bude číst. Kde je vše pochopitelné ze signatur funkcí a tříd a není třeba pátrat po skrytých tajemstvích v implementaci.
+
+Této technice předávání argumentů se odborně říká **dependency injection**.
+
+(Nezaměňujte dependency injection s „dependency injection container“, jde o něco diametrálně odlišného a kontejnerum se budeme věnovat v [druhé kapitole|container].)
+
+
+Od funkcí ke třídám
+-------------------
+
+A jak s tím souvisí třídy? Třída je komplexnější celek než jednoduchá funkce, nicméně pravidlo č. 1 platí bezezbytku i tady. Jen existuje [víc možností, jak argumenty předat|passing-dependencies]. Kupříkladu docela podobně jako v případě funkce:
+
+```php
+class Matematika
+{
+ public function soucet(float $a, float $b): float
+ {
+ return $a + $b;
+ }
+}
+
+$math = new Matematika;
+echo $math->soucet(23, 1); // 24
+```
+
+Nebo pomocí jiných metod, či přímo konstruktoru:
+
+```php
+class Soucet
+{
+ private $a;
+ private $b;
+
+ public function __construct(float $a, float $b)
+ {
+ $this->a = $a;
+ $this->b = $b;
+ }
+
+ public function spocti(): float
+ {
+ return $this->a + $this->b;
+ }
+
+}
+
+$soucet = new Soucet(23, 1);
+echo $soucet->spocti(); // 24
+```
+
+Obě ukázky jsou zcela v souladu s dependency injection.
+
+
+Reálné příklady
+---------------
+
+V reálném světe nebudete psát třídy pro sčítání čísel. Pojďme se přesunout k příkladům z praxe.
+
+Mějme třídu `Article` reprezentující článek na blogu:
+
+```php
+class Article
+{
+ public int $id;
+ public string $title;
+ public string $content;
+
+ public function save(): void
+ {
+ // uložíme článek do databáze
+ }
+}
+```
+
+a použití bude následující:
+
+```php
+$article = new Article;
+$article->title = '10 Things You Need to Know About Losing Weight';
+$article->content = 'Every year millions of people in ...';
+$article->save();
+```
+
+Metoda `save()` uloží článek do databázové tabulky. Implementovat ji za pomoci [Nette Database |/database/@home] bude hračka, nebýt jednoho zádrhelu: kde má `Article` vzít připojení k databázi, tj. objekt třídy `Nette\Database\Connection`?
+
+Zdá se, že máme spoustu možností. Může jej vzít odněkud ze statické proměnné. Nebo dědit od třídy, která spojení s databází zajistí. Nebo využít tzv. singletonu. Nebo tzv. facades, které se používají v Laravelu:
+
+```php
+use Illuminate\Support\Facades\DB;
+
+class Article
+{
+ public int $id;
+ public string $title;
+ public string $content;
+
+ public function save(): void
+ {
+ DB::insert(
+ 'INSERT INTO articles (title, content) VALUES (?, ?)',
+ [$this->title, $this->content],
+ );
+ }
+}
+```
+
+Skvělé, problém jsme vyřešili.
+
+Nebo ne?
+
+Připomeňme [#pravidlo č. 1: používej parametry]: všechna data, která třída potřebuje, jim musíme předat. Protože pokud to neuděláme a pravidlo porušíme, nastoupili jsme cestu ke špinavému kódu plného skrytých vazeb, nesrozumitelnosti, a výsledkem bude aplikace, kterou bude bolest udržovat a vyvíjet.
+
+Uživatel třídy `Article` netuší, kam metoda `save()` článek ukládá. Do databázové tabulky? Do které, ostré nebo testovací? A jak to lze změnit?
+
+Uživatel se musí podívat, jak je implementovaná metoda `save()`, kde najde použití metody `DB::insert()`. Takže musí pátrat dál, jak si tato metoda obstarává databázové spojení. A skryté vazby mohou tvořit docela dlouhý řetězec.
+
+V čistém a dobře navrženém kódu se nikdy nevyskytují skryté vazby, Laravelovské facades nebo statické proměnné. V čistém a dobře navrženém kódu se předávají argumenty:
+
+```php
+class Article
+{
+ public function save(Nette\Database\Connection $db): void
+ {
+ $db->query('INSERT INTO articles', [
+ 'title' => $this->title,
+ 'content' => $this->content,
+ ]);
+ }
+}
+```
+
+Ještě praktičtější, jak uvidíme dále, to bude konstruktorem:
+
+```php
+class Article
+{
+ private $db;
+
+ public function __construct(Nette\Database\Connection $db)
+ {
+ $this->db = $db;
+ }
+
+ public function save(): void
+ {
+ $this->db->query('INSERT INTO articles', [
+ 'title' => $this->title,
+ 'content' => $this->content,
+ ]);
+ }
+}
+```
+
+Budete-li psát třídu vyžadující ke své činnosti např. databázi, nevymýšlejte, odkud ji získat, ale nechte si ji předat. Třeba jako parametr konstruktoru nebo jiné metody. Přiznejte závislosti. Přiznejte je v API vaší třídy. Získáte srozumitelný a předvídatelný kód.
+
+A co třeba tato třída, která loguje chybové zprávy:
+
+```php
+class Logger
+{
+ public function log(string $message)
+ {
+ $file = LOG_DIR . '/log.txt';
+ file_put_contents($file, $message . "\n", FILE_APPEND);
+ }
+}
+```
+
+Co myslíte, dodrželi jsme [#pravidlo č. 1: používej parametry]?
+
+Nedodrželi.
+
+Klíčovou informaci, tedy adresář se souborem s logem, si třída *obstarává sama* z konstanty.
+
+Podívejte se na příklad použití:
+
+```php
+$logger = new Logger;
+$logger->log('Teplota je 23 °C');
+$logger->log('Teplota je 10 °C');
+```
+
+Bez znalosti implementace, dokázali byste zodpovědět otázku, kam se zprávy zapisují? Napadlo by vás, že pro fungování je potřeba existence konstanty LOG_DIR? A dokázali byste vytvořit druhou instanci, která bude zapisovat jinam? Určitě ne.
+
+Pojďme třídu opravit:
+
+```php
+class Logger
+{
+ private $file;
+
+ public function __construct(string $file)
+ {
+ $this->file = $file;
+ }
+
+ public function log(string $message)
+ {
+ file_put_contents($this->file, $message . "\n", FILE_APPEND);
+ }
+}
+```
+
+Třída je teď mnohem srozumitelnější, konfigurovatelnější a tedy užitečnější.
+
+```php
+$logger = new Logger('/cesta/k/logu.txt');
+$logger->log('Teplota je 15 °C');
+```
+
+
+Ale to mě nezajímá!
+-------------------
+
+*„Když vytvořím objekt Article a zavolám save(), tak nechci řešit databázi, prostě chci, aby se uložil do té kterou mám nastavenou v konfiguraci.“*
+
+*„Když použiju Logger, tak prostě chci, aby se zpráva zapsala, a nechci řešit kam. Ať se použije globální nastavení.“*
+
+To jsou správné připomínky.
+
+Jako příklad si ukážeme třídu rozesílající newslettery, která zaloguje, jak to dopadlo:
+
+```php
+class NewsletterDistributor
+{
+ public function distribute(): void
+ {
+ $logger = new Logger(/* ... */);
+ try {
+ $this->sendEmails();
+ $logger->log('Emaily byly rozeslány');
+
+ } catch (Exception $e) {
+ $logger->log('Došlo k chybě při rozesílání');
+ throw $e;
+ }
+ }
+}
+```
+
+Jenže nový `Logger`, který již nepoužívá konstantu `LOG_DIR`, vyžaduje v konstruktoru uvést cestu k souboru. Jak tohle vyřešit? Třídu `NewsletterDistributor` vůbec nezajímá, kam se zprávy zapisují, chce je jen zapsat.
+
+Řešením je opět [#pravidlo č. 1: používej parametry]: všechna data, která třída potřebuje, jim předáme.
+
+Takže předáme do konstruktoru cestu k logu, kterou pak použijeme při vytváření objektu `Logger`? Nikoliv. Cesta totiž nejdou data, která třída `NewsletterDistributor` potřebuje; ty potřebuje `Logger`. Třída potřebuje logger jako takový. A ten si předáme:
+
+
+```php
+class NewsletterDistributor
+{
+ private $logger;
+
+ public function __construct(Logger $logger)
+ {
+ $this->logger = $logger;
+ }
+
+ public function distribute(): void
+ {
+ try {
+ $this->sendEmails();
+ $this->logger->log('Emaily byly rozeslány');
+
+ } catch (Exception $e) {
+ $this->logger->log('Došlo k chybě při rozesílání');
+ throw $e;
+ }
+ }
+}
+```
+
+Nyní je ze signatur třídy `NewsletterDistributor` jasné, že součástí její funkčnosti je i logování. A máte možnost vyměnit logger za jiný.
+
+Zatímco v celé aplikaci si můžeme vystačit s jedinou instancí loggeru a předávat ji všude tam, kde se něco loguje, jinak je tomu v případě třídy `Article`. Její instance budeme chtít vytvářet vícekrát. Jak se vypořádat s vazbou na databázi v konstruktoru? Jako příklad si ukážeme kontroler, který po odeslání formuláře má uložit článek do databáze:
+
+```php
+class UserController extends Controller
+{
+ public function formSubmitted($data)
+ {
+ $article = new Article(/* ... */);
+ $article->title = $data->title;
+ $article->content = $data->content;
+ $article->save();
+ }
+}
+```
+
+Možné řešení se přímo nabízí: necháme si objekt databáze předat konstruktorem do `UserController` a použijeme `$article = new Article($this->db)`.
+
+Stejně jako v předchozím případě, tohle není správný postup. Databáze není závislost `UserController`, ale `Article`. Navíc ve chvíli, kdy se nějak změní konstruktor třídy `Article` (přibude nový parametr), budeme muset upravit i kód na všech místech, kde se vytváří instance.
+
+Řešením jsou továrny.
+
+
+Pravidlo č. 2: používej továrny
+-------------------------------
+
+Tím, že jsme zrušili skryté vazby a všechna data předáváme jako argumenty, získali jsme konfigurovatelnější a pružnější třídy. A proto potřebujeme ještě něco, co nám ty pružnější třídy vytvoří a nakonfiguruje. Budeme tomu říkat továrny.
+
+Pravidlo zní: pokud má třída závislosti, nech vytváření jejich instancí na továrně.
+
+Továrny jsou chytřejší náhrada operátoru `new` ve světě dependency injection.
+
+
+Továrna
+-------
+
+Továrna je třída, která vyrábí a konfiguruje objekty. Továrnu vyrábějící `Article` nazveme `ArticleFactory` a její použití v kontroleru bude následující:
+
+```php
+class UserController extends Controller
+{
+ private $articleFactory;
+
+ public function __construct(ArticleFactory $articleFactory)
+ {
+ $this->articleFactory = $articleFactory;
+ }
+
+ public function formSubmitted($data)
+ {
+ // necháme továrnu vytvořit objekt
+ $article = $this->articleFactory->create();
+ $article->title = $data->title;
+ $article->content = $data->content;
+ $article->save();
+ }
+}
+```
+
+Implementace továrny může vypadat takto:
+
+
+```php
+class ArticleFactory
+{
+ private $db;
+
+ public function __construct(Nette\Database\Connection $db)
+ {
+ $this->db = $db;
+ }
+
+ public function create(): Article
+ {
+ return new Article($this->db);
+ }
+}
+```
+
+Když se v tuto chvíli změní signatura konstruktoru třídy `Article`, jediná část kódu, která na to musí reagovat, je samotná továrna `ArticleFactory`. Veškerého dalšího kódu, který s objekty `Article` pracuje, jako například `UserController`, se to nijak nedotkne.
+
+Možná si teď klepete na čelo, jak jsme si to vlastně pomohli. Množství kódu narostlo a z controlleru se přesunulo do zvláštní třídy. Nette DI má však skryté eso v rukávu. Konceptu továren totiž rozumí a dokáže takovou službu dokonce [napsat za nás|factory]. Místo třídy `ArticleFactory` by tak stačílo vytvořit jen interface:
+
+```php
+interface ArticleFactory
+{
+ function create(): Article;
+}
+```
+
+Ale to teď trošku předbíháme, dostaneme se k tomu za chvíli.
+
+
+Shrnutí
+-------
+
+Na začátku této kapitoly jsme slibovali, že si ukážeme prostý princip, jak navrhovat aplikace. Ačkoliv princip samotný prostý je (předávej třídám data, které potřebují), to co z něj vyplývá už vyžaduje víc přemýšlení. Klidně si tuto kapitolu přečtěte několikrát.
+
+Programátoři, kteří zahodili staré zvyky a začali důsledně používat dependency injection, považují tento krok za zásadní moment v profesním životě. Otevřel se jim svět přehledných a udržitelných aplikací.
+
+Nyní si ukážeme, co je to [Dependency Injection Container|container].
+
+
+{{composer: nette/di}}
diff --git a/docs/cs/nette-container.texy b/docs/cs/nette-container.texy
new file mode 100644
index 000000000..8a00f0796
--- /dev/null
+++ b/docs/cs/nette-container.texy
@@ -0,0 +1,86 @@
+Nette DI Container
+******************
+
+.[perex]
+Nette DI je jednou z nejzajímavějších knihoven Nette. Umí generovat a automaticky aktualizovat kompilované DI kontejnery, které jsou extrémně rychlé a úžasně snadno konfigurovatelné.
+
+Podobu služeb, které má vytvářet DI kontejner, definujeme obvykle pomocí konfiguračních souborů ve [formátu NEON|/neon/format]. Kontejner, který jsme ručně vytvořili v [předchozí kapitole|container], by se zapsal takto:
+
+```neon
+parameters:
+ db:
+ dsn: 'mysql:'
+ user: root
+ password: '***'
+
+services:
+ - Nette\Database\Connection(%db.dsn%, %db.user%, %db.password%)
+ - ArticleFactory
+ - UserController
+```
+
+Zápis je opravdu stručný.
+
+Všechny závislosti deklarované v konstruktorech tříd `ArticleFactory` a `UserController` si Nette DI samo zjistí a předá díky tzv. [autowiringu|autowiring], v konfiguračním souboru proto není potřeba nic uvádět.
+Takže i když dojde ke změně parametrů, nemusíte v konfiguraci nic měnit. Nette kontejner automaticky přegeneruje. Vy se tam můžete soustředit čistě na vývoj aplikace.
+
+Pokud chceme závislosti předávat pomocí setterů, použijeme k tomu sekci [setup|services#setup].
+
+Nette DI vygeneruje přímo PHP kód kontejneru. Výsledkem je tedy soubor `.php`, který si můžete otevřít a studovat. Díky tomu přesně vidíte, jak kontejner funguje. Můžete jej také debuggovat v IDE a krokovat. A hlavně: vygenerované PHP
+je extrémně rychlé.
+
+Nette DI umí také generovat kód [továren|factory] na základě dodaného rozhraní. Proto místo třídy `ArticleFactory` nám bude stačit vytvořit v aplikaci jen interface:
+
+```php
+interface ArticleFactory
+{
+ function create(): Article;
+}
+```
+
+Celý příklad najdete [na GitHubu|https://github.com/nette-examples/di-example-doc].
+
+
+Samostatné použití
+------------------
+
+Nasazení knihovny Nette DI do aplikace je velmi snadné. Nejprve ji nainstalujeme Composerem (protože stahování zipů je tááák zastaralé):
+
+```shell
+composer require nette/di
+```
+
+Následující kód vytvoří instanci DI kontejneru podle konfigurace uložené v souboru `config.neon`:
+
+```php
+$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp');
+$class = $loader->load(function ($compiler) {
+ $compiler->loadConfig(__DIR__ . '/config.neon');
+});
+$container = new $class;
+```
+
+Kontejner se vygeneruje jen jednou, jeho kód se zapíše do cache (adresář `__DIR__ . '/temp'`) a při dalších požadavcích se už jen odsud načítá.
+
+Pro vytvoření a získání služeb slouží metody `getService()` nebo `getByType()`. Takto vytvoříme objekt `UserController`:
+
+```php
+$database = $container->getByType(UserController::class);
+$database->query('...');
+```
+
+Během vývoje je užitečné aktivovat auto-refresh mód, kdy se kontejner automaticky přegeneruje, pokud dojde ke změně jakékoliv třídy nebo konfiguračního souboru. Stačí v konstruktoru `ContainerLoader` uvést jako druhý argument `true`.
+
+```php
+$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp', true);
+```
+
+
+Použití s frameworkem Nette
+---------------------------
+
+Jak jsme si ukázali, použití Nette DI není limitované na aplikace psané v Nette Frameworku, můžete jej pomocí pouhých 3 řádků kódu nasadit kdekoliv.
+Pokud však vyvíjíte aplikace v Nette Framework, konfiguraci a vytvoření kontejneru má na starosti [Bootstrap|/application/bootstrap#toc-konfigurace-di-kontejneru].
+
+
+{{composer: nette/di}}
diff --git a/docs/cs/passing-dependencies.texy b/docs/cs/passing-dependencies.texy
new file mode 100644
index 000000000..37d5d887e
--- /dev/null
+++ b/docs/cs/passing-dependencies.texy
@@ -0,0 +1,158 @@
+Předávání závislostí
+********************
+
+
+
+Argumenty, nebo v terminologii DI „závislosti“, lze do tříd předávat těmito hlavními způsoby:
+
+* předávání konstruktorem
+* předávání metodou (tzv. setterem)
+* nastavením proměnné
+* metodou, anotací či atributem *inject*
+
+
+
+První tři způsoby platí obecně ve všech objektově orientovaných jazycích, čtvrtý je specifický pro presentery v Nette, takže o něm pojednává [samostatná kapitola |/best-practices/inject-method-attribute]. Nyní si jednotlivé možnosti přiblížíme a ukážeme na konkrétních případech.
+
+
+Předávání konstruktorem
+=======================
+
+Závislosti jsou předávány v okamžiku vytváření objektu jako argumenty konstruktoru:
+
+```php
+class MyService
+{
+ /** @var Cache */
+ private $cache;
+
+ public function __construct(Cache $service)
+ {
+ $this->cache = $service;
+ }
+}
+
+$service = new MyService($cache);
+```
+
+Tato forma je vhodná pro povinné závislosti, které třída nezbytně potřebuje ke své funkci, neboť bez nich nepůjde instanci vytvořit.
+
+Od PHP 8.0 můžeme použít kratší formu zápisu, která je funkčně ekvivaletní:
+
+```php
+// PHP 8.0
+class MyService
+{
+ public function __construct(
+ private Cache $service,
+ ) {
+ }
+}
+```
+
+Od PHP 8.1 lze proměnnou označit příznakem `readonly`, který deklaruje, že obsah proměnné se už nezmění:
+
+```php
+// PHP 8.1
+class MyService
+{
+ public function __construct(
+ private readonly Cache $service,
+ ) {
+ }
+}
+```
+
+DI kontejner předá konstruktoru závislosti automaticky pomocí [autowiringu |autowiring]. Argumenty, které takto předat nelze (např. řetězce, čísla, booleany) [zapíšeme v konfiguraci |services#Argumenty].
+
+
+Předávání setterem
+==================
+
+Závislosti jsou předávány voláním metody, která je uloží do privátní proměnné. Obvyklou konvencí pojmenování těchto metod je tvar `set*()`, proto se jim říká settery.
+
+```php
+class MyService
+{
+ /** @var Cache */
+ private $cache;
+
+ public function setCache(Cache $service): void
+ {
+ $this->cache = $service;
+ }
+}
+
+$service = new MyService;
+$service->setCache($cache);
+```
+
+Tento způsob je vhodný pro nepovinné závislosti, které nejsou pro funkci třídy nezbytné, neboť není garantováno, že objekt závislost skutečně dostane (tj. že uživatel metodu zavolá).
+
+Zároveň tento způsob připouští volat setter opakovaně a závislost tak měnit. Pokud to není žádoucí, přidáme do metody kontrolu, nebo od PHP 8.1 označíme proměnnou `$cache` příznakem `readonly`.
+
+```php
+class MyService
+{
+ /** @var Cache */
+ private $cache;
+
+ public function setCache(Cache $service): void
+ {
+ if ($this->cache) {
+ throw new RuntimeException('The dependency has already been set');
+ }
+ $this->cache = $service;
+ }
+}
+```
+
+Volání setteru definujeme v konfiraci DI kontejneru v [sekci setup |services#Setup]. I tady se využívá automatického předávání závislostí pomocí autowiringu:
+
+```neon
+services:
+ -
+ create: MyService
+ setup:
+ - setCache
+```
+
+
+Nastavením proměnné
+===================
+
+Závislosti jsou předávány zapsáním přímo do členské proměnné:
+
+```php
+class MyService
+{
+ /** @var Cache */
+ public $cache;
+}
+
+$service = new MyService;
+$service->cache = $cache;
+```
+
+Tento způsob se považuje za nevhodný, protože členská proměnná musí být deklarována jako `public`. A tudíž nemáme kontrolu nad tím, že předaná závislost bude skutečně daného typu (platilo před PHP 7.4) a přicházíme o možnost reagovat na nově přiřazenou závislost vlastním kódem, například zabránit následné změně. Zároveň se proměnná stává součástí veřejného rozhraní třídy, což nemusí být žádoucí.
+
+Nastavení proměnné definujeme v konfiraci DI kontejneru v [sekci setup |services#Setup]:
+
+```neon
+services:
+ -
+ create: MyService
+ setup:
+ - $cache = @\Cache
+```
+
+
+Jaký způsob zvolit?
+===================
+
+- konstruktor je vhodný pro povinné závislosti, které třída nezbytně potřebuje ke své funkci
+- setter je naopak vhodný pro nepovinné závislosti, nebo závislosti, které lze mít možnost dále měnit
+- veřejné proměnné vhodné nejsou
+
+
+{{composer: nette/di}}
diff --git a/docs/cs/services.texy b/docs/cs/services.texy
new file mode 100644
index 000000000..d9db18195
--- /dev/null
+++ b/docs/cs/services.texy
@@ -0,0 +1,449 @@
+Definování služeb
+*****************
+
+.[perex]
+Konfigurace je místem, kam umísťujeme definice vlastních služeb. Slouží k tomu sekce `services`.
+
+Například takto vytvoříme službu pojmenovanou `database`, což bude instance třídy `PDO`:
+
+```neon
+services:
+ database: PDO('sqlite::memory:')
+```
+
+Pojmenování služeb slouží k tomu, abychom se na ně mohli [odkazovat|#Odkazování na služby]. Pokud na službu není odkazováno, není ji potřeba pojmenovávat. Místo názvu tak použijeme jen odrážku:
+
+```neon
+services:
+ - PDO('sqlite::memory:') # anonymní služba
+```
+
+Jednořádkový zápis lze rozepsat do více řádků a tak umožnit přidání dalších klíčů, jako je například [#setup]. Aliasem pro klíč `create:` je `factory:`.
+
+```neon
+services:
+ database:
+ create: PDO('sqlite::memory:')
+ setup: ...
+```
+
+Službu poté získáme z DI kontejneru metodou `getService()` podle názvu, nebo ještě lépe metodou `getByType()` podle typu:
+
+```php
+$database = $container->getService('database');
+$database = $container->getByType(PDO::class);
+```
+
+
+Vytvoření služby
+================
+
+Nejčastěji službu vytváříme prostým vytvořením instance určité třídy:
+
+```neon
+services:
+ database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
+```
+
+Což vygeneruje tovární metodu v [DI kontejneru|container]:
+
+```php
+public function createServiceDatabase(): PDO
+{
+ return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
+}
+```
+
+Pro předání [argumentů|#Argumenty] lze alternativně použít i klíč `arguments`:
+
+```neon
+services:
+ database:
+ create: PDO
+ arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
+```
+
+Službu může vytvořit také statická metoda:
+
+```neon
+services:
+ database: My\Database::create(root, secret)
+```
+
+Odpovídá PHP kódu:
+
+```php
+public function createServiceDatabase(): PDO
+{
+ return My\Database::create('root', 'secret');
+}
+```
+
+Předpokládá se, statická metoda `My\Database::create()` má definovanou návratovou hodnotu, kterou DI kontejner potřebuje znát. Pokud ji nemá, zapíšeme typ do konfigurace:
+
+```neon
+services:
+ database:
+ create: My\Database::create(root, secret)
+ type: PDO
+```
+
+Nette DI nám dává mimořádně silné výrazové prostředky, pomocí kterých můžete zapsat téměř cokoliv. Například se [odkázat|#Odkazování na služby] na jinou službu a zavolat její metodu. Pro jednoduchost se místo `->` používá `::`
+
+```neon
+services:
+ routerFactory: App\Router\Factory
+ router: @routerFactory::create()
+```
+
+Odpovídá PHP kódu:
+
+```php
+public function createServiceRouterFactory(): App\Router\Factory
+{
+ return new App\Router\Factory;
+}
+
+public function createServiceRouter(): Router
+{
+ return $this->getService('routerFactory')->create();
+}
+```
+
+Volání metod lze řetězit za sebe stejně jako v PHP:
+
+```neon
+services:
+ foo: FooFactory::build()::get()
+```
+
+Odpovídá PHP kódu:
+
+```php
+public function createServiceFoo()
+{
+ return FooFactory::build()->get();
+}
+```
+
+
+Argumenty
+=========
+
+Pro předání argumentů lze používat i pojmenované parametry:
+
+```neon
+services:
+ database: PDO(
+ 'mysql:host=127.0.0.1;dbname=test' # poziční
+ username: root # pojmenovaný
+ password: secret # pojmenovaný
+ )
+```
+
+Při rozepsání argumentů do více řádků je používání čárek volitelné.
+
+Jako argumenty můžeme samozřejmě použít i [jiné služby|#Odkazování na služby] nebo [parametry|configuration#parametry]:
+
+```neon
+services:
+ - Foo(@anotherService, %appDir%)
+```
+
+Odpovídá PHP kódu:
+
+```php
+public function createService01(): Foo
+{
+ return new Foo($this->getService('anotherService'), '...');
+}
+```
+
+Pokud se má první argument [autowirovat|autowiring] a chceme přitom uvést argument druhý, vynecháme první znakem `_`, tedy např. `Foo(_, %appDir%)`. Nebo ještě lépe předáme jen druhý argument jako pojmenovaný parametr, např. `Foo(path: %appDir%)`.
+
+Nette DI a formát NEON nám dává mimořádně silné výrazové prostředky, pomocí kterých můžete zapsat téměř cokoliv. Argumentem tak může být nově vytvořený objekt, lze volat statické metody, metody jiných služeb, nebo pomocí speciálního zápisu i globální funkce:
+
+```neon
+services:
+ analyser: My\Analyser(
+ FilesystemIterator(%appDir%) # vytvoření objektu
+ DateTime::createFromFormat('Y-m-d') # volání statické metody
+ @anotherService # předání jiné služby
+ @http.request::getRemoteAddress() # volání metody jiné služby
+ ::getenv(NETTE_MODE) # volání globální funkce
+ )
+```
+
+Odpovídá PHP kódu:
+
+```php
+public function createServiceAnalyser(): My\Analyser
+{
+ return new My\Analyser(
+ new FilesystemIterator('...'),
+ DateTime::createFromFormat('Y-m-d'),
+ $this->getService('anotherService'),
+ $this->getService('http.request')->getRemoteAddress(),
+ getenv('NETTE_MODE')
+ );
+}
+```
+
+
+Speciální funkce
+----------------
+
+V argumentech lze také používat speciální funkce pro přetypování nebo negaci hodnot:
+
+- `not(%arg%)` negace
+- `bool(%arg%)` bezeztrátové přetypování na bool
+- `int(%arg%)` bezeztrátové přetypování na int
+- `float(%arg%)` bezeztrátové přetypování na float
+- `string(%arg%)` bezeztrátové přetypování na string
+
+```neon
+services:
+ - Foo(
+ id: int(::getenv('PROJECT_ID'))
+ productionMode: not(%debugMode%)
+ )
+```
+
+Bezztrátové přetypování se od běžného přetypování v PHP např. pomocí `(int)` liší v tom, že pro nečíselné hodnoty vyhodí výjimku.
+
+Jako argument lze předávat i více služeb. Pole všech služeb určitého typu (tj. třídy nebo rozhraní) vytvoří funkce `typed()`. Funkce vynechá služby, které mají vypnutý autowiring a lze uvést i více typů oddělených čárkou.
+
+```neon
+services:
+ - BarsDependent( typed(Bar) )
+```
+
+Předávat pole služeb můžete i automaticky pomocí [autowiringu|autowiring#Pole služeb].
+
+Pole všech služeb s určitým [tagem|#tagy] vytvoří funkce `tagged()`. Lze uvést i více tagů oddělených čárkou.
+
+```neon
+services:
+ - LoggersDependent( tagged(logger) )
+```
+
+
+Odkazování na služby
+====================
+
+Na jednotlivé služby se odkazuje pomocí zavináče a názvu služby, takže například `@database`:
+
+```neon
+services:
+ - create: Foo(@database)
+ setup:
+ - setCacheStorage(@cache.storage)
+```
+
+Odpovídá PHP kódu:
+
+```php
+public function createService01(): Foo
+{
+ $service = new Foo($this->getService('database'));
+ $service->setCacheStorage($this->getService('cache.storage'));
+ return $service;
+}
+```
+
+I na anonymní služby se lze odkazovat přes zavináč, jen místo názvu uvedeme jejich typ (třídu nebo rozhraní). Tohle ovšem obvykle není potřeba dělat díky [autowiringu|autowiring].
+
+```neon
+services:
+ - create: Foo(@Nette\Database\Connection) # nebo třeba @\PDO
+ setup:
+ - setCacheStorage(@cache.storage)
+```
+
+
+Setup
+=====
+
+V sekci setup uvádíme metody, které se mají zavolat při vytváření služby:
+
+```neon
+services:
+ database:
+ create: PDO(%dsn%, %user%, %password%)
+ setup:
+ - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
+```
+
+Odpovídá PHP kódu:
+
+```php
+public function createServiceDatabase(): PDO
+{
+ $service = new PDO('...', '...', '...');
+ $service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ return $service;
+}
+```
+
+Lze také nastavovat hodnoty proměnných. Podporováno je i přidání prvku do pole, které je potřeba zapsat v uvozovkách, aby nekolidovalo se syntaxí NEON:
+
+
+```neon
+services:
+ foo:
+ create: Foo
+ setup:
+ - $value = 123
+ - '$onClick[]' = [@bar, clickHandler]
+```
+
+Odpovídá PHP kódu:
+
+```php
+public function createServiceFoo(): Foo
+{
+ $service = new Foo;
+ $service->value = 123;
+ $service->onClick[] = [$this->getService('bar'), 'clickHandler'];
+ return $service;
+}
+```
+
+V setupu lze však volat i statické metody nebo metod jiných služeb. Aktuální službu jim předáme jako `@self`:
+
+
+```neon
+services:
+ foo:
+ create: Foo
+ setup:
+ - My\Helpers::initializeFoo(@self)
+ - @anotherService::setFoo(@self)
+```
+
+Odpovídá PHP kódu:
+
+```php
+public function createServiceFoo(): Foo
+{
+ $service = new Foo;
+ My\Helpers::initializeFoo($service);
+ $this->getService('anotherService')->setFoo($service);
+ return $service;
+}
+```
+
+
+Autowiring
+==========
+
+Pomocí klíče autowired lze službu vyřadit z autowiringu nebo jeho chování ovlivnit. Více v [kapitole o autowiringu|autowiring].
+
+```neon
+services:
+ foo:
+ create: Foo
+ autowired: false # služba foo je vyřazena z autowiringu
+```
+
+
+Tagy
+====
+
+Jednotlivým službám lze přidávat uživatelské informace v podobě tzv. tagů:
+
+```neon
+services:
+ foo:
+ create: Foo
+ tags:
+ - cached
+```
+
+Tagy mohou mít i hodnotu:
+
+```neon
+services:
+ foo:
+ create: Foo
+ tags:
+ logger: monolog.logger.event
+```
+
+Pole služeb s určitými tagy lze předat jako argument pomocí funkce `tagged()`. Lze uvést i více tagů oddělených čárkou.
+
+```neon
+services:
+ - LoggersDependent( tagged(logger) )
+```
+
+Názvy služeb lze získat z DI kontejneru metodou `findByTag()`:
+
+```php
+$names = $container->findByTag('logger');
+// $names je pole obsahující název služby a hodnotu tagu
+// např. ['foo' => 'monolog.logger.event', ...]
+```
+
+
+Režim Inject
+============
+
+Pomocí příznaku `inject: true` se aktivuje předávání závislostí přes veřejné proměnné s anotací [inject |/best-practices/inject-method-attribute#Anotace inject] a metody [inject*() |/best-practices/inject-method-attribute#metody inject].
+
+```neon
+services:
+ articles:
+ create: App\Model\Articles
+ inject: true
+```
+
+V základním nastavení je `inject` aktivováno pouze pro presentery.
+
+
+Modifikace služeb
+=================
+
+V DI kontejneru je řada služeb, které přidaly vestavěné nebo [vaše rozšíření|#rozšíření]. Definice těchto služeb lze v konfiguraci pozměnit. Třeba u služby `application.application`, což je standardně objekt `Nette\Application\Application`, můžeme změnit třídu:
+
+```neon
+services:
+ application.application:
+ create: MyApplication
+ alteration: true
+```
+
+Příznak `alteration` je informativní a říká, že jen modifikujeme existující službu.
+
+Můžeme také doplnit setup:
+
+```neon
+services:
+ application.application:
+ create: MyApplication
+ alteration: true
+ setup:
+ - '$onStartup[]' = [@resource, init]
+```
+
+Při přepisování služby můžeme chtít odstranit původní argumenty, položky setup nebo tagy, k čemuž slouží `reset`:
+
+```neon
+services:
+ application.application:
+ create: MyApplication
+ alteration: true
+ reset:
+ - arguments
+ - setup
+ - tags
+```
+
+Službu přidanou rozšířením lze také z kontejneru odstranit:
+
+```neon
+services:
+ cache.journal: false
+```
+
+{{composer: nette/di}}
diff --git a/docs/en/@home.texy b/docs/en/@home.texy
new file mode 100644
index 000000000..10c6ef2aa
--- /dev/null
+++ b/docs/en/@home.texy
@@ -0,0 +1,24 @@
+Dependency Injection
+********************
+
+.[perex]
+The `nette/di` package provides an extremely advanced compiled DI container for PHP.
+
+- [What is Dependency Injection? |introduction]
+- [What is DI Container? |container]
+- [Nette DI Container |nette-container]
+- [Configuration |configuration]
+- [Service Definitions |services]
+- [Autowiring |autowiring]
+- [Generated Factories |factory]
+- [Passing Dependencies |passing-dependencies]
+- [Creating Extensions for Nette DI|extensions]
+
+
+Installation:
+
+```shell
+composer require nette/di
+```
+
+{{composer: nette/di}}
diff --git a/docs/en/@left-menu.texy b/docs/en/@left-menu.texy
new file mode 100644
index 000000000..d195bb550
--- /dev/null
+++ b/docs/en/@left-menu.texy
@@ -0,0 +1,13 @@
+
+
+Dependency Injection
+--------------------
+- [What is DI? |introduction]
+- [What is DI Container? |container]
+- [Nette DI Container |nette-container]
+- [Configuration |configuration]
+- [Service Definitions |services]
+- [Autowiring |autowiring]
+- [Generated Factories |factory]
+- [Passing Dependencies |passing-dependencies]
+- [Creating Extensions for Nette DI|extensions]
diff --git a/docs/en/autowiring.texy b/docs/en/autowiring.texy
new file mode 100644
index 000000000..3b9a4539b
--- /dev/null
+++ b/docs/en/autowiring.texy
@@ -0,0 +1,233 @@
+Autowiring
+**********
+
+.[perex]
+Autowiring is a great feature that can automatically pass services to the constructor and other methods, so we do not need to write them at all. It saves you a lot of time.
+
+This allows us to skip the vast majority of arguments when writing service definitions. Instead of:
+
+```neon
+services:
+ articles: Model\ArticleRepository(@database, @cache.storage)
+```
+
+Just write:
+
+```neon
+services:
+ articles: Model\ArticleRepository
+```
+
+Autowiring is driven by types, so `ArticleRepository` class must be defined as follows:
+
+```php
+namespace Model;
+
+class ArticleRepository
+{
+ public function __construct(\PDO $db, \Nette\Caching\Storage $storage)
+ {}
+ public function setCacheStorage(\Nette\Caching\IStorage $storage)
+}
+```
+
+To use autowiring, there must be **just one service** for each type in the container. If there were more, autowiring would not know which one to pass and throw away an exception:
+
+```neon
+services:
+ mainDb: PDO(%dsn%, %user%, %password%)
+ tempDb: PDO('sqlite::memory:')
+ articles: Model\ArticleRepository # THROWS EXCEPTION, both mainDb and tempDb matches
+```
+
+The solution would be to either bypass autowiring and explicitly state the service name (i.e. `articles: Model\ArticleRepository(@mainDb)`). However, it is more convenient to [disable|#Disabled autowiring] autowiring of one services, or the first service [prefer|#Preferred Autowiring].
+
+
+Disabled Autowiring
+-------------------
+
+You can disable service autowiring by using the `autowired: no` option:
+
+```neon
+services:
+ mainDb: PDO(%dsn%, %user%, %password%)
+
+ tempDb:
+ create: PDO('sqlite::memory:')
+ autowired: false # removes tempDb from autowiring
+
+ articles: Model\ArticleRepository # therefore passes mainDb to constructor
+```
+
+The `articles` service does not throw the exception that there are two matching services of type `PDO` (i.e. `mainDb` and `tempDb`) that can be passed to the constructor, because it only sees the `mainDb` service.
+
+
+Preferred Autowiring
+--------------------
+
+If we have more services of the same type and one of them has the `autowired` option, this service becomes the preferred one:
+
+```neon
+services:
+ mainDb:
+ create: PDO(%dsn%, %user%, %password%)
+ autowired: PDO # makes it preferred
+
+ tempDb:
+ create: PDO('sqlite::memory:')
+
+ articles: Model\ArticleRepository
+```
+
+The `articles` service does not throw the exception that there are two matching `PDO` services (i.e. `mainDb` and `tempDb`), but uses the preferred service, i.e. `mainDb`.
+
+
+Collection of Services
+----------------------
+
+Autowiring can also pass an array of services of a particular type. Since PHP cannot natively notate the type of array items, in addition to the `array` type, a phpDoc comment with the item type like `ClassName[]` must be added:
+
+```php
+namespace Model;
+
+class ShipManager
+{
+ /**
+ * @param Shipper[] $shippers
+ */
+ public function __construct(array $shippers)
+ {}
+}
+```
+
+The DI container then automatically passes an array of services matching the given type. It will omit services that have autowiring turned off.
+
+If you can't control the form of the phpDoc comment, you can pass an array of services directly in the configuration using [`typed()`|services#Special Functions].
+
+
+Narrowing of Autowiring
+-----------------------
+
+For individual services, autowiring can be narrowed to specific classes or interfaces.
+
+Normally, autowiring passes the service to each method parameter whose type the service corresponds to. Narrowing means that we specify conditions that the types specified for the method parameters must satisfy for the service to be passed to them.
+
+Let's take an example:
+
+```php
+class ParentClass
+{}
+
+class ChildClass extends ParentClass
+{}
+
+class ParentDependent
+{
+ function __construct(ParentClass $obj)
+ {}
+}
+
+class ChildDependent
+{
+ function __construct(ChildClass $obj)
+ {}
+}
+```
+
+If we registered them all as services, autowiring would fail:
+
+```neon
+services:
+ parent: ParentClass
+ child: ChildClass
+ parentDep: ParentDependent # THROWS EXCEPTION, both parent and child matches
+ childDep: ChildDependent # passes the service 'child' to the constructor
+```
+
+The `parentDep` service throws the exception `Multiple services of type ParentClass found: parent, child` because both `parent` and `child` fit into its constructor and autowiring can not make a decision on which one to choose.
+
+For service `child`, we can therefore narrow down its autowiring to `ChildClass`:
+
+```neon
+services:
+ parent: ParentClass
+ child:
+ create: ChildClass
+ autowired: ChildClass # alternative: 'autowired: self'
+
+ parentDep: ParentDependent # THROWS EXCEPTION, the 'child' can not be autowired
+ childDep: ChildDependent # passes the service 'child' to the constructor
+```
+
+The `parentDep` service is now passed to the `parentDep` service constructor, since it is now the only matching object. The `child` service is no longer passed in by autowiring. Yes, the `child` service is still of type `ParentClass`, but the narrowing condition given for the parameter type no longer applies, i.e. it is no longer true that `ParentClass` *is a supertype* of `ChildClass`.
+
+In the case of `child`, `autowired: ChildClass` could be written as `autowired: self` as the `self` means current service type.
+
+The `autowired` key can include several classes and interfaces as array:
+
+```neon
+autowired: [BarClass, FooInterface]
+```
+
+Let's try to add interfaces to the example:
+
+```php
+interface FooInterface
+{}
+
+interface BarInterface
+{}
+
+class ParentClass implements FooInterface
+{}
+
+class ChildClass extends ParentClass implements BarInterface
+{}
+
+class FooDependent
+{
+ function __construct(FooInterface $obj)
+ {}
+}
+
+class BarDependent
+{
+ function __construct(BarInterface $obj)
+ {}
+}
+
+class ParentDependent
+{
+ function __construct(ParentClass $obj)
+ {}
+}
+
+class ChildDependent
+{
+ function __construct(ChildClass $obj)
+ {}
+}
+```
+
+When we do not limit the `child` service, it will fit into the constructors of all `FooDependent`, `BarDependent`, `ParentDependent` and `ChildDependent` classes and autowiring will pass it there.
+
+However, if we narrow its autowiring to `ChildClass` using `autowired: ChildClass` (or `self`), autowiring it only passes it to the `ChildDependent` constructor, because it requires an argument of type `ChildClass` and `ChildClass` *is of type* `ChildClass`. No other type specified for the other parameters is a superset of `ChildClass`, so the service is not passed.
+
+If we restrict it to `ParentClass` using `autowired: ParentClass`, autowiring will pass it again to the `ChildDependent` constructor (since the required type `ChildClass` is a superset of `ParentClass`) and to the `ParentDependent` constructor too, since the required type of `ParentClass` is also matching.
+
+If we restrict it to `FooInterface`, it will still autowire to `ParentDependent` (the required type `ParentClass` is a supertype of `FooInterface`) and `ChildDependent`, but additionally to the `FooDependent` constructor, but not to `BarDependent`, since `BarInterface` is not a supertype of `FooInterface`.
+
+```neon
+services:
+ child:
+ create: ChildClass
+ autowired: FooInterface
+
+ fooDep: FooDependent # passes the service child to the constructor
+ barDep: BarDependent # THROWS EXCEPTION, no service would pass
+ parentDep: ParentDependent # passes the service child to the constructor
+ childDep: ChildDependent # passes the service child to the constructor
+```
+
+
+{{composer: nette/di}}
diff --git a/docs/en/configuration.texy b/docs/en/configuration.texy
new file mode 100644
index 000000000..017ebabef
--- /dev/null
+++ b/docs/en/configuration.texy
@@ -0,0 +1,315 @@
+Configuring DI Container
+************************
+
+.[perex]
+Overview of configuration options for the Nette DI container.
+
+Nette DI container is easy to control using configuration files. They are usually written in [NEON format|/neon/format]. We recommend to use [editors with support|/best-practices/editors-and-tools#ide-editor] for this format for editing.
+
+
+"decorator .[prism-token prism-atrule]":[#Decorator]: "Decorator .[prism-token prism-comment]"
+"di .[prism-token prism-atrule]":[#DI]: "DI Container .[prism-token prism-comment]"
+"extensions .[prism-token prism-atrule]":[#Extensions]: "Install additional DI extensions .[prism-token prism-comment]"
+"includes .[prism-token prism-atrule]":[#Including files]: "Including files .[prism-token prism-comment]"
+"parameters .[prism-token prism-atrule]":[#Parameters]: "Parameters .[prism-token prism-comment]"
+"search .[prism-token prism-atrule]":[#Search]: "Automatic service registration .[prism-token prism-comment]"
+"services .[prism-token prism-atrule]":[services]: "Services .[prism-token prism-comment]"
+
+
+If you use a string that starts with `@` or has `%` anywhere in it, you need to escape it by adding another `@` or `%`. .[note]
+
+
+Parameters
+==========
+
+You can define parameters that can then be used as part of service definitions. This can help to separate out values that you will want to change more regularly.
+
+```neon
+parameters:
+ dsn: 'mysql:host=127.0.0.1;dbname=test'
+ user: root
+ password: secret
+```
+
+You can refer to `foo` parameter via `%foo%` elsewhere in any config file. They can also be used inside strings like `'%wwwDir%/images'`.
+
+Parameters do not need to be just strings, they can also be array values:
+
+```neon
+parameters:
+ mailer:
+ host: smtp.example.com
+ secure: ssl
+ user: franta@gmail.com
+ languages: [cs, en, de]
+```
+
+You can refer to single key as `%mailer.user%`.
+
+If you need to get the value of any parameter in your code, for example in your class, then pass it to this class. For example, in the constructor. There is no global configuration object which can classes query for parameter values. This would be against to the principle of dependency injection.
+
+
+Services
+========
+
+See [separate chapter|services].
+
+
+Decorator
+=========
+
+How to bulk edit all services of a certain type? Need to call a certain method for all presenters inheriting from a particular common ancestor? That's where the decorator comes from.
+
+```neon
+decorator:
+ # for all services that are instances of this class or interface
+ App\Presenters\BasePresenter:
+ setup:
+ - setProjectId(10) # call this method
+ - $absoluteUrls = true # and set the variable
+```
+
+Decorator can also be used to set [tags|services#Tags] or turn on [inject mode|services#Inject Mode].
+
+```neon
+decorator:
+ InjectableInterface:
+ tags: [mytag: 1]
+ inject: true
+```
+
+
+DI
+===
+
+Technical settings of the DI container.
+
+```neon
+di:
+ # shows DIC in Tracy Bar?
+ debugger: ... # (bool) defaults to true
+
+ # parameter types that you never autowire
+ excluded: ... # (string[])
+
+ # the class from which the DI container inherits
+ parentClass: ... # (string) defaults to Nette\DI\Container
+```
+
+
+Metadata Export
+---------------
+
+The DI container class also contains a lot of metadata. You can reduce it by reducing the metadata export.
+
+```neon
+di:
+ export:
+ # to export parameters?
+ parameters: false # (bool) defaults to true
+
+ # export tags and which ones?
+ tags: # (string[]|bool) the default is all
+ - event.subscriber
+
+ # export data for autowiring and which?
+ types: # (string[]|bool) the default is all
+ - Nette\Database\Connection
+ - Symfony\Component\Console\Application
+```
+
+If you don't use the `$container->parameters` array, you can disable parameter export. Furthermore, you can export only those tags through which you get services using the `$container->findByTag(...)` method.
+If you don't call the method at all, you can completely disable tag export with `false`.
+
+You can significantly reduce the metadata for [autowiring] by specifying the classes you use as a parameter to the `$container->getByType()` method.
+And again, if you don't call the method at all (or only in [/application/bootstrap] to get `Nette\Application\Application`), you can disable the export entirely with `false`.
+
+
+Extensions
+==========
+
+Registration of other DI extensions. In this way we add, for example, DI extension `Dibi\Bridges\Nette\DibiExtension22` under the name `dibi`:
+
+```neon
+extensions:
+ dibi: Dibi\Bridges\Nette\DibiExtension22
+```
+
+Then we configure it in it's section called also `dibi`:
+
+```neon
+dibi:
+ host: localhost
+```
+
+You can also add a extension class with parameters:
+
+```neon
+extensions:
+ application: Nette\Bridges\ApplicationDI\ApplicationExtension(%debugMode%, %appDir%, %tempDir%/cache)
+```
+
+
+Including Files
+===============
+
+Additional configuration files can be inserted in the `includes` section:
+
+```neon
+includes:
+ - parameters.php
+ - services.neon
+ - presenters.neon
+```
+
+The name `parameters.php` is not a typo, the configuration can also be written in a PHP file, which returns it as an array:
+
+```php
+ [
+ 'main' => [
+ 'dsn' => 'sqlite::memory:',
+ ],
+ ],
+];
+```
+
+If items with the same keys appear within configuration files, they will be [overwritten or merged |#Merging] in the case of arrays. Later included file has a higher priority than the previous one. The file in which the `includes` section is listed has a higher priority than the files included in it.
+
+
+Search
+======
+
+The automatic adding of services to the DI container makes work extremely pleasant. Nette automatically adds presenters to the container, but you can easily add any other classes.
+
+Just specify in which directories (and subdirectories) the classes should be search for:
+
+```neon
+search:
+ # you choose the section names yourself
+ myForms:
+ in: %appDir%/Forms
+
+ model:
+ in: %appDir%/Model
+```
+
+Usually, however, we don't want to add all the classes and interfaces, so we can filter them:
+
+```neon
+search:
+ myForms:
+ in: %appDir%/Forms
+
+ # filtering by file name (string|string[])
+ files:
+ - *Factory.php
+
+ # filtering by class name (string|string[])
+ classes:
+ - *Factory
+```
+
+Or we can select classes that inherit or implement at least one of the following classes:
+
+
+```neon
+search:
+ myForms:
+ extends:
+ - App\*Form
+ implements:
+ - App\*FormInterface
+```
+
+You can also define negative rules, ie class name masks or ancestors and if they comply, the service will not be added to the DI container:
+
+```neon
+search:
+ myForms:
+ exclude:
+ classes: ...
+ extends: ...
+ implements: ...
+```
+
+Tags can be set for added services:
+
+```neon
+search:
+ myForms:
+ tags: ...
+```
+
+
+Merging
+=======
+
+If items with the same keys appear in more configuration files, they will be overwritten or merged in the case of arrays. The later included file has a higher priority.
+
+
+
+ config1.neon |
+ config2.neon |
+ result |
+
+
+
+```neon
+items:
+ - 1
+ - 2
+```
+ |
+
+```neon
+items:
+ - 3
+```
+ |
+
+```neon
+items:
+ - 1
+ - 2
+ - 3
+```
+ |
+
+
+
+To prevent merging of a certain array use exclamation mark right after the name of the array:
+
+
+
+ config1.neon |
+ config2.neon |
+ result |
+
+
+
+```neon
+items:
+ - 1
+ - 2
+```
+ |
+
+```neon
+items!:
+ - 3
+```
+ |
+
+```neon
+items:
+ - 3
+```
+ |
+
+
+
+
+{{composer: nette/di}}
+{{maintitle: Dependency Injection Configuration}}
diff --git a/docs/en/container.texy b/docs/en/container.texy
new file mode 100644
index 000000000..0f1574cc7
--- /dev/null
+++ b/docs/en/container.texy
@@ -0,0 +1,146 @@
+What Is DI Container?
+*********************
+
+.[perex]
+Dependency injection container (DIC) is a class that can instantiate and configure objects.
+
+It may surprise you, but in many cases you don't need a dependency injection container to take advantage of dependency injection (DI for short). After all, even in [previous chapter|introduction] we showed specific examples of DI and no container was needed.
+
+However, if you need to manage a large number of different objects with many dependencies, a dependency injection container will be really useful. Which is perhaps the case for web applications built on a framework.
+
+In the previous chapter, we introduced the classes `Article` and `UserController`. Both of them have some dependencies, namely database and factory `ArticleFactory`. And for these classes, we will now create a container. Of course, for such a simple example, it doesn't make sense to have a container. But we'll create one to show how it looks and works.
+
+Here is a simple hardcoded container for the above example:
+
+```php
+class Container
+{
+ public function createDatabase(): Nette\Database\Connection
+ {
+ return new Nette\Database\Connection('mysql:', 'root', '***');
+ }
+
+ public function createArticleFactory(): ArticleFactory
+ {
+ return new ArticleFactory($this->createDatabase());
+ }
+
+ public function createUserController(): UserController
+ {
+ return new UserController($this->createArticleFactory());
+ }
+}
+```
+
+The usage would look like this:
+
+```php
+$container = new Container;
+$controller = $container->createUserController();
+```
+
+We just ask the container for the object and no longer need to know anything about how to create it or what its dependencies are; the container knows all that. The dependencies are injected automatically by the container. That's its power.
+
+So far, the container has everything hardcoded. So we take the next step and add parameters to make the container really useful:
+
+```php
+class Container
+{
+ private $parameters;
+
+ public function __construct(array $parameters)
+ {
+ $this->parameters = $parameters;
+ }
+
+ public function createDatabase(): Nette\Database\Connection
+ {
+ return new Nette\Database\Connection(
+ $this->parameters['db.dsn'],
+ $this->parameters['db.user'],
+ $this->parameters['db.password']
+ );
+ }
+
+ // ...
+}
+
+$container = new Container([
+ 'db.dsn' => 'mysql:',
+ 'db.user' => 'root',
+ 'db.password' => '***',
+]);
+```
+
+Astute readers may have noticed a problem. Every time I get an object `UserController`, a new instance `ArticleFactory` and database is also created. We definitely don't want that.
+
+So we add a method `getService()` that will return the same instances over and over again:
+
+```php
+class Container
+{
+ private $parameters;
+ private $services = [];
+
+ public function __construct(array $parameters)
+ {
+ $this->parameters = $parameters;
+ }
+
+ public function getService(string $name): object
+ {
+ if (!isset($this->services[$name])) {
+ // getService('Database') calls createDatabase()
+ $method = 'create' . $name;
+ $this->services[$name] = $this->$method();
+ }
+ return $this->services[$name];
+ }
+
+ // ...
+}
+```
+
+The first call to e.g. `$container->getService('Database')` will have `createDatabase()` create a database object, which it will store in the array `$services` and return it directly on the next call.
+
+We also modify the rest of the container to use `getService()`:
+
+```php
+class Container
+{
+ // ...
+
+ public function createArticleFactory(): ArticleFactory
+ {
+ return new ArticleFactory($this->getService('Database'));
+ }
+
+ public function createUserController(): UserController
+ {
+ return new UserController($this->getService('ArticleFactory'));
+ }
+}
+```
+
+By the way, the term service refers to any object managed by the container. Hence the method name `getService()`.
+
+Done. We have a fully functional DI container! And we can use it:
+
+```php
+$container = new Container([
+ 'db.dsn' => 'mysql:',
+ 'db.user' => 'root',
+ 'db.password' => '***',
+]);
+
+$controller = $container->getService('UserController');
+$database = $container->getService('Database');
+```
+
+As you can see, it's not difficult to write a DIC. It's notable that the objects themselves don't know that a container is creating them. Thus, it is possible to create any object in PHP this way without affecting their source code.
+
+Manually creating and maintaining a container class can become a nightmare rather quickly. Therefore, in the next chapter we will talk about [Nette DI Container|nette-container], which can generate and update itself almost automatically.
+
+
+{{composer: nette/di}}
+{{maintitle: What is Dependency Injection Container?}}
diff --git a/docs/en/extensions.texy b/docs/en/extensions.texy
new file mode 100644
index 000000000..97ff6b715
--- /dev/null
+++ b/docs/en/extensions.texy
@@ -0,0 +1,197 @@
+Creating Extensions for Nette DI
+********************************
+
+.[perex]
+Generating an DI container in addition to configuration files also affect the so-called *extensions*. We activate them in the configuration file in the `extensions` section.
+
+This is how we add the extension represented by class `BlogExtension` with name `blog`:
+
+```neon
+extensions:
+ blog: BlogExtension
+```
+
+Each compiler extension inherits from [api:Nette\DI\CompilerExtension] and can implement following methods that are called during DI compilation:
+
+1. getConfigSchema()
+2. loadConfiguration()
+3. beforeCompile()
+4. afterCompile()
+
+
+getConfigSchema() .[method]
+===========================
+
+This method is called first. It defines schema used to validate configuration parameters.
+
+Extensions are configured in a section whose name is the same as the one under which the extension was added, eg `blog`.
+
+```neon
+# same name as my extension
+blog:
+ postsPerPage: 10
+ comments: false
+```
+
+We will define a schema describing all configuration options, including their types, accepted values and possibly default values:
+
+```php
+use Nette\Schema\Expect;
+
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function getConfigSchema(): Nette\Schema\Schema
+ {
+ return Expect::structure([
+ 'postsPerPage' => Expect::int(),
+ 'allowComments' => Expect::bool()->default(true),
+ ]);
+ }
+}
+```
+
+See the [/schema/@home] for documentation. Additionally, you can specify which options can be [dynamic |/application/bootstrap#Dynamic Parameters] using `dynamic()`, for example `Expect::int()->dynamic()`.
+
+We access configuration through the `$this->config`, which is an object `stdClass`:
+
+```php
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function loadConfiguration()
+ {
+ $num = $this->config->postPerPage;
+ if ($this->config->allowComments) {
+ // ...
+ }
+ }
+}
+```
+
+
+loadConfiguration() .[method]
+=============================
+
+This method is used to add services to the container. This is done by [api:Nette\DI\ContainerBuilder]:
+
+```php
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function loadConfiguration()
+ {
+ $builder = $this->getContainerBuilder();
+ $builder->addDefinition($this->prefix('articles'))
+ ->setFactory(App\Model\HomepageArticles::class, ['@connection'])
+ ->addSetup('setLogger', ['@logger']);
+ }
+}
+```
+
+The convention is to prefix the services added by an extension with its name so that no name conflicts arise. This is done by `prefix()`, so if the extension is called 'blog', the service will be called `blog.articles`.
+
+If we need to rename a service, we can create an alias with its original name to maintain backward compatibility. Similarly this is what Nette does for eg `routing.router`, which is also available under the earlier name `router`.
+
+```php
+$builder->addAlias('router', 'routing.router');
+```
+
+
+Retrieve Services from a File
+-----------------------------
+
+We can create services using the ContainerBuilder API, but also we can add them via the familiar NEON configuration file and its `services` section. The prefix `@extension` represents the current extension.
+
+```neon
+services:
+ articles:
+ create: MyBlog\ArticlesModel(@connection)
+
+ comments:
+ create: MyBlog\CommentsModel(@connection, @extension.articles)
+
+ articlesList:
+ create: MyBlog\Components\ArticlesList(@extension.articles)
+```
+
+We will add services this way:
+
+```php
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function loadConfiguration()
+ {
+ $builder = $this->getContainerBuilder();
+
+ // load the configuration file for the extension
+ $this->compiler->loadDefinitionsFromConfig(
+ $this->loadFromFile(__DIR__ . '/blog.neon')['services'],
+ );
+ }
+}
+```
+
+
+beforeCompile() .[method]
+=========================
+
+The method is called when the container contains all the services added by individual extensions in `loadConfiguration` methods as well as user configuration files. At this phase of assembling, we can then modify service definitions or add links between them. You can use the `findByTag()` method to search for services by tags, or `findByType()` method to search by class or interface.
+
+```php
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function beforeCompile()
+ {
+ $builder = $this->getContainerBuilder();
+
+ foreach ($builder->findByTag('logaware') as $serviceName => $tagValue) {
+ $builder->getDefinition($serviceName)->addSetup('setLogger');
+ }
+ }
+}
+```
+
+
+afterCompile() .[method]
+========================
+
+At this phase, the container class is already generated as a [ClassType |/php-generator/@home#classes] object, it contains all the methods that the service creates, and is ready for caching as PHP file. We can still edit the resulting class code at this point.
+
+```php
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function afterCompile(Nette\PhpGenerator\ClassType $class)
+ {
+ $method = $class->getMethod('__construct');
+ // ...
+ }
+}
+```
+
+
+$initialization .[wiki-method]
+==============================
+
+The Configurator calls the initialization code after [container creation |/application/bootstrap#index.php], which is created by writing to an object `$this->initialization` using [method addBody() |/php-generator/@home#Method and Function Body Generator].
+
+We will show an example of how to start a session or start services that have the `run` tag using initialization code:
+
+```php
+class BlogExtension extends Nette\DI\CompilerExtension
+{
+ public function loadConfiguration()
+ {
+ // automatic session startup
+ if ($this->config->session->autoStart) {
+ $this->initialization->addBody('$this->getService("session")->start()');
+ }
+
+ // services with tag 'run' must be created after the container is instantiated
+ $builder = $this->getContainerBuilder();
+ foreach ($builder->findByTag('run') as $name => $foo) {
+ $this->initialization->addBody('$this->getService(?);', [$name]);
+ }
+ }
+}
+```
+
+
+{{composer: nette/di}}
diff --git a/docs/en/factory.texy b/docs/en/factory.texy
new file mode 100644
index 000000000..f0cc1e9b9
--- /dev/null
+++ b/docs/en/factory.texy
@@ -0,0 +1,233 @@
+Generated Factories
+*******************
+
+.[perex]
+Nette DI can automatically generate factory code based on the interface, which saves you from writing code.
+
+A factory is a class that creates and configures objects. It therefore passes their dependencies to them as well. We showed what such a factory looks like in [introduction|introduction#factory]:
+
+```php
+class ArticleFactory
+{
+ private Nette\Database\Connection $db;
+
+ public function __construct(Nette\Database\Connection $db)
+ {
+ $this->db = $db;
+ }
+
+ public function create(): Article
+ {
+ return new Article($this->db);
+ }
+}
+```
+
+Nette DI can generate factory code automatically. All you have to do is create an interface and Nette DI will generate an implementation. The interface must have exactly one method named `create` and declare a return type:
+
+```php
+interface ArticleFactory
+{
+ function create(): Article;
+}
+```
+
+So the factory `ArticleFactory` has a method `create` that creates objects `Article`. Class `Article` might look like the following, for example:
+
+```php
+class Article
+{
+ private $db;
+
+ public function __construct(Nette\Database\Connection $db)
+ {
+ $this->db = $db;
+ }
+}
+```
+
+Add the factory to the configuration file:
+
+```neon
+services:
+ - ArticleFactory
+```
+
+Nette DI will generate the corresponding factory implementation.
+
+Thus, in the code that uses the factory, we request the object by interface and Nette DI uses the generated implementation:
+
+```php
+class UserController
+{
+ private $articleFactory;
+
+ public function __construct(ArticleFactory $articleFactory)
+ {
+ $this->articleFactory = $articleFactory;
+ }
+
+ public function foo()
+ {
+ // let the factory create an object
+ $article = $this->articleFactory->create();
+ }
+}
+```
+
+
+Parameterized Factory
+=====================
+
+The factory method `create` can accept parameters which it then passes to the constructor. For example, let's add an article author ID to the class `Article`:
+
+```php
+class Article
+{
+ private $db;
+ private $authorId;
+
+ public function __construct(Nette\Database\Connection $db, int $authorId)
+ {
+ $this->db = $db;
+ $this->authorId = $authorId;
+ }
+}
+```
+
+We will also add the parameter to the factory:
+
+```php
+interface ArticleFactory
+{
+ function create(int $authorId): Article;
+}
+```
+
+Because the parameter in the constructor and the parameter in the factory have the same name, Nette DI will pass them automatically.
+
+
+Advanced Definition
+===================
+
+The definition can also be written in multi-line form using the key `implement`:
+
+```neon
+services:
+ articleFactory:
+ implement: ArticleFactory
+```
+
+When writing in this longer way, it is possible to provide additional arguments for the constructor in the key `arguments` and additional configuration using `setup`, just as for normal services.
+
+Example: if the method `create()` did not accept the parameter `$authorId`, we could specify a fixed value in the configuration that would be passed to the constructor `Article`:
+
+```neon
+services:
+ articleFactory:
+ implement: ArticleFactory
+ arguments:
+ authorId: 123
+```
+
+Or, conversely, if `create()` did accept the parameter `$authorId` but it was not part of the constructor and was passed by method `Article::setAuthorId()`, we would refer to it in section `setup`:
+
+```neon
+services:
+ articleFactory:
+ implement: ArticleFactory
+ setup:
+ - setAuthorId($authorId)
+```
+
+
+Accessor
+========
+
+Besides factories, Nette can also generate so called accessors. Accessor is an object with `get()` method returning a particular service from the DI container. Multiple `get()` calls will always return the same instance.
+
+Accessors bring lazy-loading to dependencies. Let's have a class logging errors to a special database. If the database connection would be passed as a dependency in its constructor, the connection would need to be always created although it would be used only rarely when an error appears so the connection would stay mostly unused.
+Instead, the class can pass an accessor and when its `get()` method is called, only then the database object is created:
+
+How to create an accessor? Write an interface only and Nette DI will generate the implementation. The interface must have exactly one method called `get` and must declare the return type:
+
+```php
+interface PDOAccessor
+{
+ function get(): PDO;
+}
+```
+
+Add the accessor to the configuration file together with the definition of the service the accessor will return:
+
+```neon
+services:
+ - PDOAccessor
+ - PDO(%dsn%, %user%, %password%)
+```
+
+The accessor returns a service of type `PDO` and because there's only one such service in the configuration, the accessor will return it. With multiple configured services of that type you can specify which one should be returned using its name, for example `- PDOAccessor(@db1)`.
+
+
+Multifactory/Accessor
+=====================
+So far, the factories and accessors could only create or return just one object. A multifactory combined with an accessor can be created as well. The interface of such multifactory class can consist of multiple methods called `create()` and `get()`, for example:
+
+```php
+interface MultiFactory
+{
+ function createArticle(): Article;
+ function createFoo(): Model\Foo;
+ function getDb(): PDO;
+}
+```
+
+Instead of passing multiple generated factories and accessors, you can pass just one complex multifactory.
+
+Alternatively, you can use `create()` and `get()` with a parameter instead of multiple methods:
+
+```php
+interface MultiFactoryAlt
+{
+ function create($name);
+ function get($name): PDO;
+}
+```
+
+In this case, `MultiFactory::createArticle()` does the same thing as `MultiFactoryAlt::create('article')`. However, the alternative syntax has a few disadvantages. It's not clear which `$name` values are supported and the return type cannot be specified in the interface when using multiple different `$name` values.
+
+
+Definition with a List
+----------------------
+Hos to define a multifactory in your configuration? Let's create three services which will be returned by the multifactory, and the multifactory itself:
+
+```neon
+services:
+ article: Article
+ - Model\Foo
+ - PDO(%dsn%, %user%, %password%)
+ - MultiFactory(
+ article: @article # createArticle()
+ foo: @Model\Foo # createFoo()
+ db: @\PDO # getDb()
+ )
+```
+
+
+Definition with Tags
+--------------------
+
+Another option how to define a multifactory is to use [tags|services#Tags]:
+
+```neon
+services:
+ - App\Router\RouterFactory::createRouter
+ - App\Model\DatabaseAccessor(
+ db1: @database.db1.explorer
+ )
+```
+
+{{composer: nette/di}}
+/--comment
+TODO: extensive update
+\--
diff --git a/docs/en/introduction.texy b/docs/en/introduction.texy
new file mode 100644
index 000000000..daaf35081
--- /dev/null
+++ b/docs/en/introduction.texy
@@ -0,0 +1,473 @@
+What Is Dependency Injection?
+*****************************
+
+.[perex]
+This chapter introduces you to the basic programming practices that underpin the entire Nette framework and that you should follow when writing your own applications. These are the basics needed to write clean, understandable, and maintainable code.
+
+If you learn and follow these rules, the framework will be there for you every step of the way. It will handle routine tasks for you and make you as comfortable as possible so you can focus on the logic itself.
+
+The principles we will show here are quite simple. You have nothing to worry about.
+
+
+Remember Your First Program?
+----------------------------
+
+We have no idea what language you wrote it in, but if it were PHP, it would probably look something like this:
+
+```php
+function addition(float $a, float $b): float
+{
+ return $a + $b;
+}
+
+echo addition(23, 1); // prints 24
+```
+
+A few trivial lines of code, yet so many key concepts are hidden in them. We see that there are variables. That code is broken down into smaller units, which are functions, for example. That we pass them input arguments and they return results. All that's missing are conditions and loops.
+
+The fact that we pass input to a function and it returns a result is a perfectly understandable concept that is used in other fields, such as mathematics.
+
+A function has a signature, which consists of its name, a list of parameters and their types, and finally the type of return value. As users, we are interested in the signature; we usually don't need to know anything about the internal implementation.
+
+Now imagine that the signature of a function looks like this:
+
+```php
+function addition(float $x): float
+```
+
+An addition with one parameter? That's weird... How about this?
+
+```php
+function addition(): float
+```
+
+That's really weird, isn't it? How do you think the function is used?
+
+```php
+echo addition(); // what does it prints?
+```
+
+Looking at such code, we are confused. Not only a beginner would not understand it, even a skilled programmer would not understand such code.
+
+Wondering what such a function would actually look like inside? Where would it get the addends? It would probably get them *somehow* on its own, like this:
+
+```php
+function addition(): float
+{
+ $a = Input::get('a');
+ $b = Input::get('b');
+ return $a + $b;
+}
+```
+
+It turns out that there are hidden bindings to other functions (or static methods) in the body of the function, and to find out where the addends actually come from, we have to dig further.
+
+
+Not This Way!
+-------------
+
+The design we have just shown is the essence of many negative features:
+
+- the function signature pretended that it didn't need addends, which confused us
+- we have no idea how to make the function calculate with two other numbers
+- we had to look into the code to see where it takes the addends
+- we discovered hidden bindings
+- to fully understand, we need to explore these bindings as well
+
+And is it even the job of the addition function to procure inputs? Of course it isn't. Its responsibility is only to add.
+
+
+We don't want to encounter such code, and we certainly don't want to write it. The remedy is simple: go back to basics and just use parameters:
+
+
+```php
+function addition(float $a, float $b): float
+{
+ return $a + $b;
+}
+```
+
+
+Rule #1: Use Parameters
+-----------------------
+
+The most important rule is: **all data that functions or classes need must be passed to them**.
+
+If we break this rule, it will be impossible to make the code understandable, clean and sustainable.
+
+If we follow it, we're on our way to code without hidden constraints. Towards code that is understandable not only to the author, but to anyone who reads it afterwards. Where everything is understandable from the signatures of functions and classes and there is no need to search for hidden secrets in the implementation.
+
+This technique of passing arguments is technically called **dependency injection**.
+
+(Don't confuse dependency injection with a "dependency injection container"; it is something radically different, and we'll cover containers in [next chapter|container].)
+
+
+From Functions to Classes
+-------------------------
+
+And how do classes relate to this? A class is a more complex entity than a simple function, but rule #1 applies here as well. There are just [more ways to pass arguments|passing-dependencies]. For example, quite similar to the case of a function:
+
+```php
+class Math
+{
+ public function addition(float $a, float $b): float
+ {
+ return $a + $b;
+ }
+}
+
+$math = new Math;
+echo $math->addition(23, 1); // 24
+```
+
+Or by using other methods, or the constructor directly:
+
+```php
+class Addition
+{
+ private $a;
+ private $b;
+
+ public function __construct(float $a, float $b)
+ {
+ $this->a = $a;
+ $this->b = $b;
+ }
+
+ public function calculate(): float
+ {
+ return $this->a + $this->b;
+ }
+
+}
+
+$addition = new Addition(23, 1);
+echo $addition->calculate(); // 24
+```
+
+Both examples are completely in compliance with dependency injection.
+
+
+Real-Life Examples
+------------------
+
+In the real world, you won't write classes to add numbers. Let's move on to real-life examples.
+
+Let's have a class `Article` representing a blog article:
+
+```php
+class Article
+{
+ public int $id;
+ public string $title;
+ public string $content;
+
+ public function save(): void
+ {
+ // save the article to the database
+ }
+}
+```
+
+and the usage will be as follows:
+
+```php
+$article = new Article;
+$article->title = '10 Things You Need to Know About Losing Weight';
+$article->content = 'Every year millions of people in ...';
+$article->save();
+```
+
+Method `save()` will store the article in a database table. Implementing it using [Nette Database |/database/@home] would be a piece of cake, if it weren't for one hitch: where does `Article` get the database connection, i.e. the class object `Nette\Database\Connection`?
+
+It seems we have plenty of options. It can take it from some static variable. Or inherit from the class that will provide the database connection. Or take advantage of a so-called singleton. Or the so-called facades that are used in Laravel:
+
+```php
+use Illuminate\Support\Facades\DB;
+
+class Article
+{
+ public int $id;
+ public string $title;
+ public string $content;
+
+ public function save(): void
+ {
+ DB::insert(
+ 'INSERT INTO articles (title, content) VALUES (?, ?)',
+ [$this->title, $this->content],
+ );
+ }
+}
+```
+
+Great, we've solved the problem.
+
+Or have we?
+
+Recall [#rule #1: use parameters]: we have to pass all the data the class needs to them. Because if we don't, and we break the rule, we've started down the path to dirty code full of hidden bindings, incomprehensibility, and the result will be an application that's a pain to maintain and develop.
+
+The user of class `Article` has no idea where method `save()` stores the article. In a database table? In which one, production or development? And how can this be changed?
+
+The user has to look at how the method `save()` is implemented to find the use of the method `DB::insert()`. So he has to search further to find out how this method procures a database connection. And hidden bindings can form quite a long chain.
+
+Hidden bindings, Laravel facades, or static variables are never present in clean, well-designed code. In clean and well-designed code, arguments are passed:
+
+```php
+class Article
+{
+ public function save(Nette\Database\Connection $db): void
+ {
+ $db->query('INSERT INTO articles', [
+ 'title' => $this->title,
+ 'content' => $this->content,
+ ]);
+ }
+}
+```
+
+Even more practical, as we'll see next, is to use a constructor:
+
+```php
+class Article
+{
+ private $db;
+
+ public function __construct(Nette\Database\Connection $db)
+ {
+ $this->db = $db;
+ }
+
+ public function save(): void
+ {
+ $this->db->query('INSERT INTO articles', [
+ 'title' => $this->title,
+ 'content' => $this->content,
+ ]);
+ }
+}
+```
+
+If you are going to write a class that requires a database, for example, don't figure out where to get it from, but let it be passed to you. Perhaps as a parameter to a constructor or other method. Declare dependencies. Expose them in the API of your class. You'll get understandable and predictable code.
+
+How about this class that logs error messages:
+
+```php
+class Logger
+{
+ public function log(string $message)
+ {
+ $file = LOG_DIR . '/log.txt';
+ file_put_contents($file, $message . "\n", FILE_APPEND);
+ }
+}
+```
+
+What do you think, did we follow [#rule #1: use parameters]?
+
+We didn't.
+
+The class *obtains* the key information, the directory containing the log file, from a constant.
+
+See an example usage:
+
+```php
+$logger = new Logger;
+$logger->log('The temperature is 23 °C');
+$logger->log('The temperature is 10 °C');
+```
+
+Without knowing the implementation, could you answer the question where the messages are written? Would it suggest to you that the existence of the LOG_DIR constant is necessary for it to work? And would you be able to create a second instance that writes to a different location? Certainly not.
+
+Let's fix the class:
+
+```php
+class Logger
+{
+ private $file;
+
+ public function __construct(string $file)
+ {
+ $this->file = $file;
+ }
+
+ public function log(string $message)
+ {
+ file_put_contents($this->file, $message . "\n", FILE_APPEND);
+ }
+}
+```
+
+The class is now much clearer, more configurable and therefore more useful.
+
+```php
+$logger = new Logger('/path/to/log.txt');
+$logger->log('The temperature is 15 °C');
+```
+
+
+But I Don’t Care!
+-----------------
+
+*"When I create an Article object and call save(), I don't want to deal with the database, I just want it to be saved to the one I have set in the configuration. "*
+
+*"When I use Logger, I just want the message to be written, and I don't want to deal with where. Let the global settings be used. "*
+
+These are correct comments.
+
+As an example, let's take a class that sends out newsletters and logs how that went:
+
+```php
+class NewsletterDistributor
+{
+ public function distribute(): void
+ {
+ $logger = new Logger(/* ... */);
+ try {
+ $this->sendEmails();
+ $logger->log('Emails have been sent out');
+
+ } catch (Exception $e) {
+ $logger->log('An error occurred during the sending');
+ throw $e;
+ }
+ }
+}
+```
+
+However, the new `Logger`, which no longer uses the `LOG_DIR` constant, requires the path to the file in the constructor. How to solve this? The `NewsletterDistributor` class doesn't care where the messages are written, it just wants to write them.
+
+The solution is again [#rule #1: use parameters]: pass all the data the class needs to it.
+
+So we pass the path to the log to the constructor, which we then use when creating the `Logger` object? No. Because the path is not the data that the `NewsletterDistributor` class needs; that's what `Logger` needs. The class needs the logger itself. And we're going to pass that:
+
+
+```php
+class NewsletterDistributor
+{
+ private $logger;
+
+ public function __construct(Logger $logger)
+ {
+ $this->logger = $logger;
+ }
+
+ public function distribute(): void
+ {
+ try {
+ $this->sendEmails();
+ $this->logger->log('Emails have been sent out');
+
+ } catch (Exception $e) {
+ $this->logger->log('An error occurred during the sending');
+ throw $e;
+ }
+ }
+}
+```
+
+Now it is clear from the signatures of class `NewsletterDistributor` that logging is part of its functionality. And you have the option to replace the logger with another one.
+
+While in the whole application we can be happy with a single instance of the logger and pass it wherever something is logged, it is different in the case of the `Article` class. We will want to create multiple instances of it. How to deal with the database dependency in the constructor? As an example, let's take a controller that is supposed to save an article to the database after submitting a form:
+
+```php
+class UserController extends Controller
+{
+ public function formSubmitted($data)
+ {
+ $article = new Article(/* ... */);
+ $article->title = $data->title;
+ $article->content = $data->content;
+ $article->save();
+ }
+}
+```
+
+A possible solution is suggested: pass the database object to the `UserController` by the constructor and use `$article = new Article($this->db)`.
+
+As in the previous case, this is not the correct practice. The database is not a `UserController` dependency, but an `Article` dependency. Moreover, the moment the constructor of the `Article` class is somehow changed (a new parameter is added), we will have to modify the code in all the places where instances are created.
+
+The solution is factories.
+
+
+Rule #2: Use Factories
+----------------------
+
+By removing the hidden bindings and passing all data as arguments, we get more configurable and flexible classes. Therefore, we still need something to create and configure those more flexible classes. We'll call it a factory.
+
+The rule of thumb is: if a class has dependencies, leave the creation of their instances to the factory.
+
+Factories are a smarter replacement for the `new` operator in the dependency injection world.
+
+
+Factory
+-------
+
+A factory is a class that creates and configures objects. The factory that produces `Article` will be called `ArticleFactory` and its use in the controller will be as follows:
+
+```php
+class UserController extends Controller
+{
+ private $articleFactory;
+
+ public function __construct(ArticleFactory $articleFactory)
+ {
+ $this->articleFactory = $articleFactory;
+ }
+
+ public function formSubmitted($data)
+ {
+ // let the factory create an object
+ $article = $this->articleFactory->create();
+ $article->title = $data->title;
+ $article->content = $data->content;
+ $article->save();
+ }
+}
+```
+
+A factory implementation might look like this:
+
+
+```php
+class ArticleFactory
+{
+ private $db;
+
+ public function __construct(Nette\Database\Connection $db)
+ {
+ $this->db = $db;
+ }
+
+ public function create(): Article
+ {
+ return new Article($this->db);
+ }
+}
+```
+
+At this point, when the signature of the class constructor `Article` changes, the only part of the code that needs to react to this is the factory `ArticleFactory`. Any other code that works with `Article` objects, such as `UserController`, is unaffected.
+
+You may be tapping your forehead right now wondering how we actually helped ourselves. The amount of code has grown and moved from the controller to a separate class. However, Nette DI has a hidden ace up its sleeve. It understands the concept of factories and can even [write such a service for us|factory]. So instead of the `ArticleFactory` class, we could just create an interface:
+
+```php
+interface ArticleFactory
+{
+ function create(): Article;
+}
+```
+
+But we're getting a little ahead of that now, we'll get to that in a minute.
+
+
+Summary
+-------
+
+At the beginning of this chapter, we promised to demonstrate a simple principle of how to design applications. Although the principle itself is simple (give the classes the data they need), what follows from it requires more thought. Feel free to read this chapter several times.
+
+Programmers who have thrown out old habits and started using dependency injection consistently consider this a pivotal moment in their professional lives. It opened up a world of clear and sustainable applications.
+
+Now we will see what [Dependency Injection Container|container] is.
+
+
+{{composer: nette/di}}
diff --git a/docs/en/nette-container.texy b/docs/en/nette-container.texy
new file mode 100644
index 000000000..e18de70da
--- /dev/null
+++ b/docs/en/nette-container.texy
@@ -0,0 +1,90 @@
+Nette DI Container
+******************
+
+.[perex]
+Nette DI is one of the most interesting Nette libraries. It can generate and automatically update compiled DI containers that are extremely fast and amazingly easy to configure.
+
+The services to be created by a DI container are usually defined using configuration files in [NEON format|/neon/format]. The container we manually created in [previous section|container] would be written as follows:
+
+```neon
+parameters:
+ db:
+ dsn: 'mysql:'
+ user: root
+ password: '***'
+
+services:
+ - Nette\Database\Connection(%db.dsn%, %db.user%, %db.password%)
+ - ArticleFactory
+ - UserController
+```
+
+The notation is really brief.
+
+All dependencies declared in the constructors of the `ArticleFactory` and `UserController` classes are found and passed by Nette DI itself thanks to the so-called [autowiring], so there is no need to specify anything in the configuration file.
+So even if the parameters change, you don't need to change anything in the configuration. Nette will automatically regenerate the container. You can concentrate there purely on application development.
+
+If you want to pass dependencies using setters, use the [setup|services#setup] section to do so.
+
+Nette DI will directly generate the PHP code for the container. The result is thus a `.php` file that you can open and study. This allows you to see exactly how the container works. You can also debug it in the IDE and step through it. And most importantly: the generated PHP
+is extremely fast.
+
+Nette DI can also generate [factory] code based on the supplied interface. Therefore, instead of the `ArticleFactory` class, we only need to create an interface in the application:
+
+```php
+interface ArticleFactory
+{
+ function create(): Article;
+}
+```
+
+You can find the full example [on GitHub|https://github.com/nette-examples/di-example-doc].
+
+
+Standalone Use
+--------------
+
+Utilization the Nette DI library in an application is very easy. First we install it with Composer (because downloading zip files is so outdated):
+
+```shell
+composer require nette/di
+```
+
+The following code creates an instance of the DI container according to the configuration stored in the `config.neon` file:
+
+```php
+$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp');
+$class = $loader->load(function ($compiler) {
+ $compiler->loadConfig(__DIR__ . '/config.neon');
+});
+$container = new $class;
+```
+
+The container is generated only once, its code is written to the cache (the `__DIR__ . '/temp'` directory) and on subsequent requests it is only read from there.
+
+The `getService()` or `getByType()` methods are used to create and retrieve services. This is how we create the `UserController` object:
+
+```php
+$database = $container->getByType(UserController::class);
+$database->query('...');
+```
+
+During development, it is useful to enable auto-refresh mode, where the container is automatically regenerated if any class or configuration file is changed. Just provide `true` as the second argument in the `ContainerLoader` constructor.
+
+```php
+$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp', true);
+```
+
+
+Using It with the Nette Framework
+---------------------------------
+
+As we have shown, the use of Nette DI is not limited to applications written in the Nette Framework, you can deploy it anywhere with just 3 lines of code.
+However, if you are developing applications in the Nette Framework, the configuration and creation of the container is handled by [Bootstrap|/application/bootstrap#toc-di-container-configuration].
+
+
+{{composer: nette/di}}
+
+/--comment
+TODO: extensive update
+\--
diff --git a/docs/en/passing-dependencies.texy b/docs/en/passing-dependencies.texy
new file mode 100644
index 000000000..4927c3af0
--- /dev/null
+++ b/docs/en/passing-dependencies.texy
@@ -0,0 +1,158 @@
+Passing Dependencies
+********************
+
+
+
+Arguments, or "dependencies" in DI terminology, can be passed to classes in the following main ways:
+
+* passing by constructor
+* passing by method (called a setter)
+* by setting a property
+* by method, annotation or attribute *inject*
+
+
+
+The first three methods apply in general in all object-oriented languages, the fourth is specific to Nette presenters, so it is discussed in [separate chapter |/best-practices/inject-method-attribute]. We will now take a closer look at each of these options and show them with specific examples.
+
+
+Constructor Injection
+=====================
+
+Dependencies are passed as arguments to the constructor when the object is created:
+
+```php
+class MyService
+{
+ /** @var Cache */
+ private $cache;
+
+ public function __construct(Cache $service)
+ {
+ $this->cache = $service;
+ }
+}
+
+$service = new MyService($cache);
+```
+
+This form is useful for mandatory dependencies that the class absolutely needs to function, as without them the instance cannot be created.
+
+Since PHP 8.0, we can use a shorter form of notation that is functionally equivalent:
+
+```php
+// PHP 8.0
+class MyService
+{
+ public function __construct(
+ private Cache $service,
+ ) {
+ }
+}
+```
+
+As of PHP 8.1, a property can be marked with a flag `readonly` that declares that the contents of the property will not change:
+
+```php
+// PHP 8.1
+class MyService
+{
+ public function __construct(
+ private readonly Cache $service,
+ ) {
+ }
+}
+```
+
+DI container passes dependencies to the constructor automatically using [autowiring]. Arguments that cannot be passed in this way (e.g. strings, numbers, booleans) [write in configuration |services#Arguments].
+
+
+Setter Injection
+================
+
+Dependencies are passed by calling a method that stores them in a private properties. The usual naming convention for these methods is of the form `set*()`, which is why they are called setters.
+
+```php
+class MyService
+{
+ /** @var Cache */
+ private $cache;
+
+ public function setCache(Cache $service): void
+ {
+ $this->cache = $service;
+ }
+}
+
+$service = new MyService;
+$service->setCache($cache);
+```
+
+This method is useful for optional dependencies that are not necessary for the class function, since it is not guaranteed that the object will actually receive them (i.e., that the user will call the method).
+
+At the same time, this method allows the setter to be called repeatedly to change the dependency. If this is not desirable, add a check to the method, or as of PHP 8.1, mark the property `$cache` with the `readonly` flag.
+
+```php
+class MyService
+{
+ /** @var Cache */
+ private $cache;
+
+ public function setCache(Cache $service): void
+ {
+ if ($this->cache) {
+ throw new RuntimeException('The dependency has already been set');
+ }
+ $this->cache = $service;
+ }
+}
+```
+
+The setter call is defined in the DI container configuration in [section setup |services#Setup]. Also here the automatic passing of dependencies is used by autowiring:
+
+```neon
+services:
+ -
+ create: MyService
+ setup:
+ - setCache
+```
+
+
+Property Injection
+==================
+
+Dependencies are passed directly to the property:
+
+```php
+class MyService
+{
+ /** @var Cache */
+ public $cache;
+}
+
+$service = new MyService;
+$service->cache = $cache;
+```
+
+This method is considered inappropriate because the property must be declared as `public`. Hence, we have no control over whether the passed dependency will actually be of the specified type (this was true before PHP 7.4) and we lose the ability to react to the newly assigned dependency with our own code, for example to prevent subsequent changes. At the same time, the property becomes part of the public interface of the class, which may not be desirable.
+
+The setting of the variable is defined in the DI container configuration in [section setup |services#Setup]:
+
+```neon
+services:
+ -
+ create: MyService
+ setup:
+ - $cache = @\Cache
+```
+
+
+Which Way to Choose?
+====================
+
+- constructor is suitable for mandatory dependencies that the class needs to function
+- the setter, on the other hand, is suitable for optional dependencies, or dependencies that can be changed
+- public variables are not recommended
+
+
+{{composer: nette/di}}
diff --git a/docs/en/services.texy b/docs/en/services.texy
new file mode 100644
index 000000000..81b91e4cf
--- /dev/null
+++ b/docs/en/services.texy
@@ -0,0 +1,449 @@
+Service Definitions
+*******************
+
+.[perex]
+Configuration is where we place the definitions of custom services. This is done in section `services`.
+
+For example, this is how we create a service named `database`, which will be an instance of class `PDO`:
+
+```neon
+services:
+ database: PDO('sqlite::memory:')
+```
+
+The naming of services is used to allow us to [reference|#Referencing Services] them. If a service is not referenced, there is no need to name it. So we just use a bullet point instead of a name:
+
+```neon
+services:
+ - PDO('sqlite::memory:') # anonymous service
+```
+
+A one-line entry can be broken up into multiple lines to allow additional keys to be added, such as [#setup]. The alias for the `create:` key is `factory:`.
+
+```neon
+services:
+ database:
+ create: PDO('sqlite::memory:')
+ setup: ...
+```
+
+We then retrieve the service from the DI container using the method `getService()` by name, or better yet, the method `getByType()` by type:
+
+```php
+$database = $container->getService('database');
+$database = $container->getByType(PDO::class);
+```
+
+
+Creating a Service
+==================
+
+Most often, we create a service by simply creating an instance of a class:
+
+```neon
+services:
+ database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
+```
+
+Which will generate a factory method in [DI container|container]:
+
+```php
+public function createServiceDatabase(): PDO
+{
+ return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
+}
+```
+
+Alternatively, a key `arguments` can be used to pass [arguments|#Arguments]:
+
+```neon
+services:
+ database:
+ create: PDO
+ arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
+```
+
+A static method can also create a service:
+
+```neon
+services:
+ database: My\Database::create(root, secret)
+```
+
+Corresponds to PHP code:
+
+```php
+public function createServiceDatabase(): PDO
+{
+ return My\Database::create('root', 'secret');
+}
+```
+
+A static method `My\Database::create()` is assumed to have a defined return value that the DI container needs to know. If it does not have it, we write the type to the configuration:
+
+```neon
+services:
+ database:
+ create: My\Database::create(root, secret)
+ type: PDO
+```
+
+Nette DI gives you extremely powerful expression facilities to write almost anything. For example, to [refer|#Referencing Services] to another service and call its method. For simplicity, `::` is used instead of `->`.
+
+```neon
+services:
+ routerFactory: App\Router\Factory
+ router: @routerFactory::create()
+```
+
+Corresponds to PHP code:
+
+```php
+public function createServiceRouterFactory(): App\Router\Factory
+{
+ return new App\Router\Factory;
+}
+
+public function createServiceRouter(): Router
+{
+ return $this->getService('routerFactory')->create();
+}
+```
+
+Method calls can be chained together as in PHP:
+
+```neon
+services:
+ foo: FooFactory::build()::get()
+```
+
+Corresponds to PHP code:
+
+```php
+public function createServiceFoo()
+{
+ return FooFactory::build()->get();
+}
+```
+
+
+Arguments
+=========
+
+Named parameters can also be used to pass arguments:
+
+```neon
+services:
+ database: PDO(
+ 'mysql:host=127.0.0.1;dbname=test' # positional
+ username: root # named
+ password: secret # named
+ )
+```
+
+The use of commas is optional when breaking arguments into multiple lines.
+
+Of course, we can also use [other services|#Referencing Services] or [parameters|configuration#parameters] as arguments:
+
+```neon
+services:
+ - Foo(@anotherService, %appDir%)
+```
+
+Corresponds to PHP code:
+
+```php
+public function createService01(): Foo
+{
+ return new Foo($this->getService('anotherService'), '...');
+}
+```
+
+If the first argument is [autowired|autowiring] and you want to specify the second one, omit the first one with the `_` character, for example `Foo(_, %appDir%)`. Or better yet, pass only the second argument as a named parameter, e.g. `Foo(path: %appDir%)`.
+
+Nette DI and the NEON format give you extremely powerful expressive facilities to write almost anything. Thus an argument can be a newly created object, you can call static methods, methods of other services, or even global functions using special notation:
+
+```neon
+services:
+ analyser: My\Analyser(
+ FilesystemIterator(%appDir%) # create object
+ DateTime::createFromFormat('Y-m-d') # call static method
+ @anotherService # passing another service
+ @http.request::getRemoteAddress() # calling another service method
+ ::getenv(NETTE_MODE) # call a global function
+ )
+```
+
+Corresponds to PHP code:
+
+```php
+public function createServiceAnalyser(): My\Analyser
+{
+ return new My\Analyser(
+ new FilesystemIterator('...'),
+ DateTime::createFromFormat('Y-m-d'),
+ $this->getService('anotherService'),
+ $this->getService('http.request')->getRemoteAddress(),
+ getenv('NETTE_MODE')
+ );
+}
+```
+
+
+Special Functions
+-----------------
+
+You can also use special functions in arguments to cast or negate values:
+
+- `not(%arg%)` negation
+- `bool(%arg%)` lossless cast to bool
+- `int(%arg%)` lossless cast to int
+- `float(%arg%)` lossless cast to float
+- `string(%arg%)` lossless cast to string
+
+```neon
+services:
+ - Foo(
+ id: int(::getenv('PROJECT_ID'))
+ productionMode: not(%debugMode%)
+ )
+```
+
+Lossless rewriting differs from normal PHP rewriting, e.g. using `(int)`, in that it throws an exception for non-numeric values.
+
+Multiple services can be passed as arguments. An array of all services of a particular type (i.e., class or interface) is created by function `typed()`. The function will omit services that have autowiring disabled, and multiple types separated by a comma can be specified.
+
+```neon
+services:
+ - BarsDependent( typed(Bar) )
+```
+
+You can also pass an array of services automatically using [autowiring|autowiring#Collection of Services].
+
+An array of all services with a certain [tag|#tags] is created by function `tagged()`. Multiple tags separated by a comma can be specified.
+
+```neon
+services:
+ - LoggersDependent( tagged(logger) )
+```
+
+
+Referencing Services
+====================
+
+Individual services are referenced using character `@` and name, so for example `@database`:
+
+```neon
+services:
+ - create: Foo(@database)
+ setup:
+ - setCacheStorage(@cache.storage)
+```
+
+Corresponds to PHP code:
+
+```php
+public function createService01(): Foo
+{
+ $service = new Foo($this->getService('database'));
+ $service->setCacheStorage($this->getService('cache.storage'));
+ return $service;
+}
+```
+
+Even anonymous services can be referenced using a callback, just specify their type (class or interface) instead of their name. However, this is usually not necessary due to [autowiring|autowiring].
+
+```neon
+services:
+ - create: Foo(@Nette\Database\Connection) # or @\PDO
+ setup:
+ - setCacheStorage(@cache.storage)
+```
+
+
+Setup
+=====
+
+In the setup section we list the methods to be called when creating the service:
+
+```neon
+services:
+ database:
+ create: PDO(%dsn%, %user%, %password%)
+ setup:
+ - setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
+```
+
+Corresponds to PHP code:
+
+```php
+public function createServiceDatabase(): PDO
+{
+ $service = new PDO('...', '...', '...');
+ $service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ return $service;
+}
+```
+
+Properites can also be set. Adding an element to an array is also supported, and should be written in quotes so as not to conflict with NEON syntax:
+
+
+```neon
+services:
+ foo:
+ create: Foo
+ setup:
+ - $value = 123
+ - '$onClick[]' = [@bar, clickHandler]
+```
+
+Corresponds to PHP code:
+
+```php
+public function createServiceFoo(): Foo
+{
+ $service = new Foo;
+ $service->value = 123;
+ $service->onClick[] = [$this->getService('bar'), 'clickHandler'];
+ return $service;
+}
+```
+
+However, static methods or methods of other services can also be called in the setup. We pass the actual service to them as `@self`:
+
+
+```neon
+services:
+ foo:
+ create: Foo
+ setup:
+ - My\Helpers::initializeFoo(@self)
+ - @anotherService::setFoo(@self)
+```
+
+Corresponds to PHP code:
+
+```php
+public function createServiceFoo(): Foo
+{
+ $service = new Foo;
+ My\Helpers::initializeFoo($service);
+ $this->getService('anotherService')->setFoo($service);
+ return $service;
+}
+```
+
+
+Autowiring
+==========
+
+The autowired key can be used to exclude a service from autowiring or to influence its behavior. See [chapter on autowiring|autowiring] for more information.
+
+```neon
+services:
+ foo:
+ create: Foo
+ autowired: false # foo is removed from autowiring
+```
+
+
+Tags
+====
+
+User information can be added to individual services in the form of tags:
+
+```neon
+services:
+ foo:
+ create: Foo
+ tags:
+ - cached
+```
+
+Tags can also have a value:
+
+```neon
+services:
+ foo:
+ create: Foo
+ tags:
+ logger: monolog.logger.event
+```
+
+An array of services with certain tags can be passed as an argument using the function `tagged()`. Multiple tags separated by a comma can also be specified.
+
+```neon
+services:
+ - LoggersDependent( tagged(logger) )
+```
+
+Service names can be obtained from the DI container using the method `findByTag()`:
+
+```php
+$names = $container->findByTag('logger');
+// $names is an array containing the service name and tag value
+// i.e. ['foo' => 'monolog.logger.event', ...]
+```
+
+
+Inject Mode
+===========
+
+The `inject: true` flag is used to activate the passing of dependencies via public variables with the [inject |/best-practices/inject-method-attribute#Inject Annotations] annotation and the [inject*() |/best-practices/inject-method-attribute#inject Methods] methods.
+
+```neon
+services:
+ articles:
+ create: App\Model\Articles
+ inject: true
+```
+
+By default, `inject` is only activated for presenters.
+
+
+Modification of Services
+========================
+
+There are a number of services in the DI container that have been added by built-in or [your extension|#di-extensions]. The definitions of these services can be modified in the configuration. For example, for service `application.application`, which is by default an object `Nette\Application\Application`, we can change the class:
+
+```neon
+services:
+ application.application:
+ create: MyApplication
+ alteration: true
+```
+
+The `alteration` flag is informative and says that we are just modifying an existing service.
+
+We can also add a setup:
+
+```neon
+services:
+ application.application:
+ create: MyApplication
+ alteration: true
+ setup:
+ - '$onStartup[]' = [@resource, init]
+```
+
+When rewriting a service, we may want to remove the original arguments, setup items or tags, which is what `reset` is for:
+
+```neon
+services:
+ application.application:
+ create: MyApplication
+ alteration: true
+ reset:
+ - arguments
+ - setup
+ - tags
+```
+
+A service added by extension can also be removed from the container:
+
+```neon
+services:
+ cache.journal: false
+```
+
+{{composer: nette/di}}